update editor page

Signed-off-by: Puqns67 <me@puqns67.icu>
This commit is contained in:
Puqns67 2023-09-17 02:17:11 +08:00
parent 2f8246cfdf
commit a5c0f4c35c
Signed by: Puqns67
GPG Key ID: 9669DF042554F536
33 changed files with 933 additions and 378 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

View File

@ -61,10 +61,6 @@
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>

View File

@ -32,7 +32,8 @@ class Account(private val repository: AccountRepository) {
attributes: RedirectAttributes,
@CookieValue("TOKEN", required = false) token: String?,
@RequestParam("name") name: String,
@RequestParam("password") password: String
@RequestParam("password") password: String,
@RequestParam("redirect", required = false) redirect: String?
): String {
if (this.getCurrentUser(token) != null) return error(attributes, "登录", "当前已登录账户")
val user = repository.findByName(name) ?: return error(attributes, "登录", "账户不存在", "/login")
@ -41,6 +42,7 @@ class Account(private val repository: AccountRepository) {
user.updateLoginTime()
repository.save(user)
updateToken(response, user.token)
redirect?.let { return "redirect:/${it}" }
return "redirect:/"
}
@ -51,15 +53,21 @@ class Account(private val repository: AccountRepository) {
@CookieValue("TOKEN", required = false) token: String?,
@RequestParam("name") name: String,
@RequestParam("password") password: String,
@RequestParam("password_confirm") passwordConfirm: String,
@RequestParam("age", required = false) age: Int?,
@RequestParam("gender", required = false) gender: String?,
@RequestParam("phone", required = false) phone: String?,
@RequestParam("email", required = false) email: String?,
@RequestParam("address", required = false) address: String?
@RequestParam("address", required = false) address: String?,
@RequestParam("redirect", required = false) redirect: String?
): String {
if (this.getCurrentUser(token) != null) return error(attributes, "注册", "当前已登录账户")
val user = repository.save(User(name, password, age, gender, phone, email, address))
if (name.isBlank()) return error(attributes, "注册", "用户名不能为空", "/register")
if (password.isBlank()) return error(attributes, "注册", "密码不能为空", "/register")
if (password != passwordConfirm) return error(attributes, "更新", "密码与确认密码不相同", "/register")
val user = repository.save(User(name, password, age, gender, phone, email, address, false))
updateToken(response, user.token)
redirect?.let { return "redirect:/${it}" }
return "redirect:/"
}
@ -85,6 +93,7 @@ class Account(private val repository: AccountRepository) {
user.update(name, password, age, gender, phone, email, address)
repository.save(user)
updateToken(response, user.token)
redirect?.let { return "redirect:/${it}" }
return "redirect:/account"
}
@ -94,7 +103,7 @@ class Account(private val repository: AccountRepository) {
@RequestParam("redirect", required = false) redirect: String?
): String {
updateToken(response, "", age = 0)
redirect?.let { return it }
redirect?.let { return "redirect:/${it}" }
return "redirect:/"
}
}

View File

@ -1,9 +1,120 @@
package team8.fruitable.controller.action
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.servlet.mvc.support.RedirectAttributes
import team8.fruitable.controller.util.Util.Companion.error
import team8.fruitable.datebase.entity.Item
import team8.fruitable.datebase.entity.Tag
import team8.fruitable.datebase.entity.User
import team8.fruitable.datebase.repository.AccountRepository
import team8.fruitable.datebase.repository.ItemRepository
import team8.fruitable.datebase.repository.TagRepository
import java.io.File
import java.util.*
@Controller
@RequestMapping("/action/edit/item")
class ItemEditor {
class ItemEditor(
private val accountRepository: AccountRepository,
private val itemRepository: ItemRepository,
private val tagRepository: TagRepository
) {
@Value("\${data.picture}")
lateinit var pictureUploadPath: String
private fun getCurrentUser(token: String?): User? {
return token?.let(accountRepository::findByToken)
}
private fun hasAdminPermissions(user: User?): Boolean {
return user?.isAdmin ?: false
}
private fun hasAdminPermissions(token: String?): Boolean {
return this.hasAdminPermissions(this.getCurrentUser(token))
}
private fun autoCreateTag(tags: List<String>): MutableList<Tag> {
val result: MutableList<Tag> = mutableListOf()
for (i in tags) {
val oldTag = tagRepository.findByName(i);
if (oldTag != null) {
result.add(oldTag)
} else {
val newTag = Tag(i)
tagRepository.save(newTag)
result.add(newTag)
}
}
return result
}
private fun autoCreateTag(tags: String): MutableList<Tag> {
return this.autoCreateTag(tags.split(" "))
}
private fun uploadPicture(file: MultipartFile): String {
val uuid = UUID.randomUUID().toString()
file.transferTo(File("${pictureUploadPath}${File.separator}${uuid}"))
return uuid
}
@PostMapping("/create")
fun create(
attributes: RedirectAttributes,
@CookieValue("TOKEN", required = false) token: String?,
@RequestParam("name") name: String,
@RequestParam("price") price: Double,
@RequestParam("description", required = false) description: String?,
@RequestParam("picture") picture: MultipartFile,
@RequestParam("tag", required = false) tag: String?,
@RequestParam("redirect", required = false) redirect: String?
): String {
if (!this.hasAdminPermissions(token)) return error(attributes, "创建商品", "账户无权限")
if (name.isBlank()) return error(attributes, "更新商品", "商品名不能为空")
if (price == 0.0) return error(attributes, "更新商品", "商品价格不能为0")
itemRepository.save(Item(name, price, description, uploadPicture(picture), tag?.let { this.autoCreateTag(it) }))
redirect?.let { return "redirect:/${it}" }
return "redirect:/editor?use=item"
}
@PostMapping("/update/{id}")
fun update(
attributes: RedirectAttributes,
@CookieValue("TOKEN", required = false) token: String?,
@PathVariable("id") id: Long,
@RequestParam("name") name: String,
@RequestParam("price") price: Double,
@RequestParam("description", required = false) description: String?,
@RequestParam("picture", required = false) picture: MultipartFile?,
@RequestParam("tag", required = false) tag: String?,
@RequestParam("redirect", required = false) redirect: String?
): String {
if (!this.hasAdminPermissions(token)) return error(attributes, "更新商品", "账户无权限")
if (name.isBlank()) return error(attributes, "更新商品", "商品名不能为空")
if (price == 0.0) return error(attributes, "更新商品", "商品价格不能为0")
val item = itemRepository.findById(id).orElse(null) ?: return error(attributes, "更新商品", "未找到目标商品")
item.update(name, price, description, picture?.let { uploadPicture(it) }, tag?.let { this.autoCreateTag(it) })
itemRepository.save(item)
redirect?.let { return "redirect:/${it}" }
return "redirect:/editor?use=item"
}
@PostMapping("/delete/{id}")
fun delete(
attributes: RedirectAttributes,
@CookieValue("TOKEN", required = false) token: String?,
@PathVariable("id") id: Long,
@RequestParam("redirect", required = false) redirect: String?
): String {
if (!this.hasAdminPermissions(token)) return error(attributes, "删除商品", "账户无权限")
val item = itemRepository.findById(id).orElse(null) ?: return error(attributes, "删除商品", "未找到目标商品")
item.update(isRemoved = true)
itemRepository.save(item)
redirect?.let { return "redirect:/${it}" }
return "redirect:/editor?use=item"
}
}

View File

@ -1,9 +1,94 @@
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.RequestMapping
import org.springframework.web.bind.annotation.*
import org.springframework.web.servlet.mvc.support.RedirectAttributes
import team8.fruitable.controller.util.Util.Companion.error
import team8.fruitable.datebase.entity.User
import team8.fruitable.datebase.repository.AccountRepository
@Controller
@RequestMapping("/action/edit/user")
class UserEditor {
class UserEditor(private val accountRepository: AccountRepository) {
private fun getCurrentUser(token: String?): User? {
return token?.let(accountRepository::findByToken)
}
private fun hasAdminPermissions(user: User?): Boolean {
return user?.isAdmin ?: false
}
private fun hasAdminPermissions(token: String?): Boolean {
return this.hasAdminPermissions(this.getCurrentUser(token))
}
@PostMapping("/create")
fun create(
attributes: RedirectAttributes,
@CookieValue("TOKEN", required = false) token: String?,
@RequestParam("name") name: String,
@RequestParam("password") password: String,
@RequestParam("age", required = false) age: Int?,
@RequestParam("gender", required = false) gender: String?,
@RequestParam("phone", required = false) phone: String?,
@RequestParam("email", required = false) email: String?,
@RequestParam("address", required = false) address: String?,
@RequestParam("is_admin", required = false) isAdmin: Boolean?,
@RequestParam("redirect", required = false) redirect: String?
): String {
if (!this.hasAdminPermissions(token)) return error(attributes, "创建用户", "账户无权限")
if (name.isBlank()) return error(attributes, "创建用户", "用户名不能为空", "/editor?use=user")
if (password.isBlank()) return error(attributes, "创建用户", "密码不能为空", "/editor?use=user")
accountRepository.save(User(name, password, age, gender, phone, email, address, isAdmin))
redirect?.let { return "redirect:/${it}" }
return "redirect:/editor?use=user"
}
@PostMapping("/update/{id}")
fun update(
response: HttpServletResponse,
attributes: RedirectAttributes,
@CookieValue("TOKEN", required = false) token: String?,
@PathVariable("id") id: Long,
@RequestParam("name") name: String,
@RequestParam("password") password: String,
@RequestParam("age", required = false) age: Int?,
@RequestParam("gender", required = false) gender: String?,
@RequestParam("phone", required = false) phone: String?,
@RequestParam("email", required = false) email: String?,
@RequestParam("address", required = false) address: String?,
@RequestParam("is_admin", required = false) isAdmin: Boolean?,
@RequestParam("redirect", required = false) redirect: String?
): String {
val currentUser = this.getCurrentUser(token) ?: return error(attributes, "更新用户", "账户未登录")
if (!this.hasAdminPermissions(currentUser)) return error(attributes, "更新用户", "账户无权限")
val user = accountRepository.findById(id).orElse(null) ?: return error(attributes, "更新用户", "未找到此用户", "/editor?use=user")
user.update(name, password, age, gender, phone, email, address, isAdmin)
if (currentUser.id == id) {
val cookie = Cookie("TOKEN", user.token)
cookie.path = "/"
cookie.maxAge = 2678400
response.addCookie(cookie)
}
redirect?.let { return "redirect:/${it}" }
return "redirect:/editor?use=user"
}
@PostMapping("/delete/{id}")
fun delete(
attributes: RedirectAttributes,
@CookieValue("TOKEN", required = false) token: String?,
@PathVariable("id") id: Long,
@RequestParam("redirect", required = false) redirect: String?
): String {
val currentUser = this.getCurrentUser(token) ?: return error(attributes, "删除用户", "账户未登录")
if (!this.hasAdminPermissions(currentUser)) return error(attributes, "删除用户", "账户无权限")
if (currentUser.id == id) return error(attributes, "删除用户", "无法删除当前使用的账户", "/editor?use=user")
val user = accountRepository.findById(id).orElse(null) ?: return error(attributes, "删除用户", "未找到此用户", "/editor?use=user")
accountRepository.delete(user)
redirect?.let { return "redirect:/${it}" }
return "redirect:/editor?use=user"
}
}

View File

@ -11,13 +11,17 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes
import team8.fruitable.controller.util.Util
import team8.fruitable.datebase.entity.User
import team8.fruitable.datebase.repository.AccountRepository
import team8.fruitable.datebase.repository.ItemRepository
import team8.fruitable.datebase.repository.PagebleAccountRepository
import team8.fruitable.datebase.repository.PagebleItemRepository
@Controller
class Editor(
private val accountRepository: AccountRepository,
private val pagebleAccountRepository: PagebleAccountRepository
private val itemRepository: ItemRepository,
private val pagebleAccountRepository: PagebleAccountRepository,
private val pagebleItemRepository: PagebleItemRepository
) {
private fun getCurrentUser(token: String?): User? {
return token?.let(accountRepository::findByToken)
@ -40,8 +44,8 @@ class Editor(
"ALL" to "全部",
"ID" to "ID",
"NAME" to "名称",
"CREATE_DATE" to "注册时间",
"LAST_LOGIN_DATE" to "最后登录时间",
"TIME_CREATE" to "注册时间",
"TIME_LOGIN" to "最后登录时间",
"AGE" to "年龄",
"GENDER" to "性别",
"PHONE" to "手机号码",
@ -64,14 +68,31 @@ class Editor(
attributes: RedirectAttributes,
@CookieValue("TOKEN", required = false) token: String?,
@RequestParam("use", defaultValue = "user") use: String,
@RequestParam("action", defaultValue = "nothing") action: String,
@RequestParam("target", required = false) target: Long?,
@RequestParam("search_type", required = false) searchType: String?,
@RequestParam("search_content", required = false) searchContent: String?,
@RequestParam("page", required = false) page: Int?,
): String {
val user = this.getCurrentUser(token) ?: return Util.error(attributes, "更新", "账户未登录", "/login")
if (!this.hasAdminPermissions(user)) return Util.error(attributes, "编辑", "账户无权限编辑网站")
model["using"] = use
model["tabs"] = editorTabs
if (searchContent != null) model["searching"] = searchContent
val pageRequested = PageRequest.of(page ?: 0, 15)
val data = when (use) {
"item" -> pagebleItemRepository.findAll(pageRequested)
else -> pagebleAccountRepository.findAll(pageRequested)
}
model["data"] = data
model["pages"] = (page ?: 0).let {
var result: Array<Pair<Boolean, Int>> = emptyArray()
for (i in (it - 5)..(it + 5)) {
if (i < 0 || i >= data.totalPages) continue
result += (i == it) to i
}
result
}
when (use) {
"item" -> {
model["useItemEditor"] = true
@ -81,7 +102,35 @@ class Editor(
else -> {
model["useUserEditor"] = true
model["selects"] = editorSearchTypesForUser
model["data"] = pagebleAccountRepository.findAll(PageRequest.of(page ?: 0, 10))
}
}
when (action) {
"creating" -> model["isCreating"] = true
"updating" -> model["isUpdating"] = true
"deleting" -> model["isDeleting"] = true
else -> model["isNothing"] = true
}
if (action == "updating" || action == "deleting") {
model["target"] = when (use) {
"item" -> {
target?.let {
itemRepository.findById(it)
.orElse(null) ?: return Util.error(attributes, "编辑", "无法找到目标商品")
} ?: return Util.error(attributes, "编辑", "目标商品为空")
}
else -> {
val targetUser = target?.let {
accountRepository.findById(it)
.orElse(null) ?: return Util.error(attributes, "编辑", "无法找到目标用户")
} ?: return Util.error(attributes, "编辑", "目标用户为空")
if (action == "updating") when (targetUser.gender) {
"M" -> model["isGenderAsMale"] = true
"F" -> model["isGenderAsFemale"] = true
else -> model["isGenderAsUnknown"] = true
}
targetUser
}
}
}
return "editor"

View File

@ -5,7 +5,6 @@ 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.mvc.support.RedirectAttributes
import team8.fruitable.controller.util.Util.Companion.error
import team8.fruitable.datebase.entity.User

View File

@ -1,6 +1,7 @@
package team8.fruitable.datebase.entity
import jakarta.persistence.*
import java.time.LocalDateTime
@Entity
@Table(name = "items")
@ -10,15 +11,27 @@ class Item(
@Column(name = "id", nullable = false)
var id: Long? = null,
@Column(name= "name", length = 32, nullable = false)
@Column(name = "name", length = 32, nullable = false)
var name: String? = null,
@Column(name="price", nullable = false)
@Column(name = "price", nullable = false)
var price: Double? = null,
@Column(name="description", length=320, nullable = true)
@Column(name = "time_create", nullable = false)
var createTime: LocalDateTime = LocalDateTime.now(),
@Column(name = "time_edit", nullable = false)
var editTime: LocalDateTime = LocalDateTime.now(),
@Column(name = "description", length = 320, nullable = true)
var description: String? = null,
@Column(name = "picture", length = 36, nullable = true)
var picture: String? = null,
@Column(name = "is_removed", nullable = false)
var isRemoved: Boolean? = false,
@ManyToOne
@JoinColumn(name = "carts")
var carted: User? = null,
@ -28,8 +41,48 @@ class Item(
var ordered: Order? = null,
@OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.LAZY, mappedBy = "tagedItem")
var tags: MutableList<Tag> = mutableListOf<Tag>(),
var tags: MutableList<Tag> = mutableListOf(),
@OneToOne(mappedBy = "item")
var recommend: Recommend? = null,
)
) {
constructor(name: String, price: Double) : this() {
this.name = name
this.price = price
}
constructor(
name: String,
price: Double,
description: String? = null,
picture: String? = null,
tags: MutableList<Tag>? = null,
isRemoved: Boolean? = null
) : this(name, price) {
if (!description.isNullOrBlank()) this.description = description
if (!picture.isNullOrBlank()) this.picture = picture
tags?.let { this.tags.addAll(it) }
isRemoved?.let { this.isRemoved = it }
}
fun update(
name: String? = null,
price: Double? = null,
description: String? = null,
picture: String? = null,
tags: MutableList<Tag>? = null,
isRemoved: Boolean? = null
) {
if (!name.isNullOrBlank()) this.name = name
this.price = price?.let { if (it <= 0) null else it }
if (!description.isNullOrBlank()) this.description = description
if (!picture.isNullOrBlank()) this.picture = picture
tags?.let { this.tags.addAll(it) }
isRemoved?.let { this.isRemoved = it }
this.updateEditTime()
}
fun updateEditTime() {
this.editTime = LocalDateTime.now()
}
}

View File

@ -16,4 +16,8 @@ class Tag(
@ManyToOne
@JoinColumn(name = "taged")
var tagedItem: Item? = null
)
) {
constructor(name: String) : this() {
this.name = name
}
}

View File

@ -1,6 +1,5 @@
package team8.fruitable.datebase.entity
import com.fasterxml.jackson.annotation.JsonView
import jakarta.persistence.*
import team8.fruitable.util.Util
import java.time.LocalDateTime
@ -12,65 +11,47 @@ 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")
@JsonView(UserView::class)
var carts: MutableList<Item> = mutableListOf(),
@OneToMany(cascade = [(CascadeType.ALL)], fetch = FetchType.LAZY, mappedBy = "user")
@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)
@ -83,13 +64,15 @@ class User(
gender: String?,
phone: String?,
email: String?,
address: String?
address: String?,
isAdmin: Boolean?
) : this(name, password) {
this.age = age
this.gender = gender
this.phone = phone
this.email = email
this.address = address
this.age = age?.let { if (it <= 0) null else it }
if (!gender.isNullOrBlank()) this.gender = gender
if (!phone.isNullOrBlank()) this.phone = phone
if (!email.isNullOrBlank()) this.email = email
if (!address.isNullOrBlank()) this.address = address
isAdmin?.let { this.isAdmin = it }
}
private final fun genPassword(password: String): String {
@ -108,11 +91,11 @@ class User(
) {
if (!name.isNullOrBlank()) this.name = name
if (!password.isNullOrBlank()) this.updatePassword(password)
this.age = age
this.age = age?.let { if (it <= 0) null else it }
if (!gender.isNullOrBlank()) this.gender = gender
this.phone = phone
this.email = email
this.address = address
if (!phone.isNullOrBlank()) this.phone = phone
if (!email.isNullOrBlank()) this.email = email
if (!address.isNullOrBlank()) this.address = address
isAdmin?.let { this.isAdmin = it }
this.updateToken()
}

View File

@ -1,6 +1,5 @@
package team8.fruitable.datebase.repository
import org.springframework.data.repository.CrudRepository
import org.springframework.data.repository.PagingAndSortingRepository
import team8.fruitable.datebase.entity.User

View File

@ -0,0 +1,8 @@
package team8.fruitable.datebase.repository
import org.springframework.data.repository.PagingAndSortingRepository
import team8.fruitable.datebase.entity.Item
interface PagebleItemRepository : PagingAndSortingRepository<Item, Long> {
fun findByName(name: String): Item?
}

View File

@ -0,0 +1,8 @@
package team8.fruitable.datebase.repository
import org.springframework.data.repository.CrudRepository
import team8.fruitable.datebase.entity.Tag
interface TagRepository : CrudRepository<Tag, Long> {
fun findByName(name: String): Tag?
}

View File

@ -1,3 +1,4 @@
debug: true
spring:
datasource:
url: jdbc:mariadb://localhost:3306/fruitable
@ -12,3 +13,5 @@ server:
encoding:
charset: UTF-8
force-response: true
data:
picture: /home/puqns67/IdeaProjects/fruitable/data/picture

View File

@ -1,23 +0,0 @@
/**
* edit.js by Puqns_67
*/
function getID(element) {
return element.parentElement.parentElement.getAttribute("id");
}
window.addEventListener("DOMContentLoaded", () => {
let displayer = document.getElementById("Displayer");
Array.from(document.getElementsByClassName("update")).forEach((v) => {
v.addEventListener("click", function () {
displayer.src = `info.action?as=update.jsp&id=${getID(this)}`;
});
});
Array.from(document.getElementsByClassName("remove")).forEach((v) => {
v.addEventListener("click", function () {
displayer.src = `info.action?as=remove.jsp&id=${getID(this)}`;
});
});
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
../../../../data

View File

@ -1,92 +0,0 @@
@font-face {
font-family: "Normal";
src: url("../fonts/华文圆体-Regular.ttf") format("ttf");
}
body {
display: flex;
margin: auto;
flex-direction: column;
align-items: center;
}
div {
display: flex;
}
#Contents {
flex-direction: column;
width: 100%;
height: 500px;
}
#Contents > .Title {
justify-content: space-between;
}
#Contents > .Editors {
flex: 4 0 0;
flex-direction: row;
justify-content: space-between;
width: auto;
margin: 5px;
padding: 5px;
background-color: rgba(0, 60, 130, 0.8);
border: 3px solid rgba(0, 120, 255, 0.8);
border-radius: 15px;
}
#Contents > .Editors > .ResultPanel {
color: wheat;
border: 3px solid skyblue;
border-spacing: 0;
border-radius: 10px;
}
#Contents > .Editors > .ResultPanel td {
white-space: nowrap;
border: 1px solid cornflowerblue;
}
#Contents > .Editors > .ResultPanel > thead {
background-color: #044488;
}
#Contents > .Editors > .ResultPanel > tbody {
background-color: #008080;
}
#Contents > .Editors > .EditPanel {
flex: 1 0 0;
margin: 5px;
padding: 5px;
background-color: rgba(0, 60, 130, 0.8);
border: 3px solid rgba(0, 120, 255, 0.8);
border-radius: 15px;
}
#Contents > .Editors > .EditPanel > .Panel {
border: 0;
}
#Contents > .Pages > * {
color: wheat;
margin-right: 3px;
border: 3px solid skyblue;
border-radius: 10px;
background-color: cadetblue;
}
#Contents > .Pages > *:last-child {
margin-right: inherit;
}
#Contents > .Pages > span {
color: green;
}
@media (min-width: 1280px) {
#Contents {
width: 1280px;
}
}

View File

@ -0,0 +1,96 @@
@font-face {
font-family: "Normal";
src: url("../fonts/华文圆体-Regular.ttf") format("ttf");
}
body {
display: flex;
margin: auto;
flex-direction: column;
align-items: center;
}
div {
display: flex;
}
#Contents {
flex-direction: column;
width: 100%;
height: 500px;
> .Title {
justify-content: space-between;
margin: 5px;
padding: 5px;
color: wheat;
background-color: rgba(0, 60, 130, 0.8);
border: 3px solid rgba(0, 120, 255, 0.8);
border-spacing: 0;
border-radius: 15px;
}
> .Editors {
flex-direction: row;
justify-content: space-between;
width: auto;
> * {
justify-content: center;
margin: 5px;
padding: 5px;
color: wheat;
background-color: rgba(0, 60, 130, 0.8);
border: 3px solid rgba(0, 120, 255, 0.8);
border-spacing: 0;
border-radius: 15px;
font-family: "Normal", system-ui;
}
> .ResultPanel {
flex: 2 auto;
td {
border: 1px solid cornflowerblue;
}
> thead {
background-color: #044488;
}
> tbody {
background-color: #008080;
}
}
> .EditPanel {
flex: 1 auto;
}
}
> .Pages {
margin: 5px;
padding: 5px;
color: wheat;
background-color: rgba(0, 60, 130, 0.8);
border: 3px solid rgba(0, 120, 255, 0.8);
border-spacing: 0;
border-radius: 15px;
> * {
color: wheat;
margin-right: 3px;
border: 3px solid skyblue;
border-radius: 10px;
background-color: cadetblue;
}
> *:last-child {
margin-right: inherit;
}
> span {
color: green;
}
}
}

View File

@ -1,9 +0,0 @@
@font-face {
font-family: "Normal";
src: url("../fonts/华文圆体-Regular.ttf") format("ttf");
}
h2 {
font: "Normal";
color: wheat;
}

View File

@ -3,25 +3,25 @@
<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="text/javascript" src="scripts/footer.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/form.css">
<link type="text/css" rel="stylesheet" href="styles/user.css">
<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>
<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/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>
<script src="/scripts/lib/anime.min.js"></script>
<script async src="/scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header }}
{{>header}}
<!-- 页面内容 -->
<div id="Contents">
@ -38,7 +38,7 @@
<div class="TabFormItem">
<label class="ItemName" for="name">用户名</label>
<input class="ItemInput" id="name" type="text" name="name" placeholder="请输入新用户名"
value="{{ user.name }}"/>
value="{{user.name}}"/>
</div>
<div class="TabFormItem">
@ -55,36 +55,36 @@
<div class="TabFormItem">
<label class="ItemName" for="age">年龄</label>
<input class="ItemInput" id="age" type="number" name="age" placeholder="请输入新年龄"
{{# user.age }}value="{{ user.age }}"{{/user.age}}/>
{{#user.age}}value="{{user.age}}"{{/user.age}}/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="phone">手机号码</label>
<input class="ItemInput" id="phone" type="tel" name="phone" placeholder="请输入新手机号"
{{# user.phone }}value="{{ user.phone }}{{/ user.phone }}"/>
{{#user.phone}}value="{{user.phone}}{{/user.phone}}"/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="email">邮箱</label>
<input class="ItemInput" id="email" type="email" name="email" placeholder="请输入新邮箱"
{{# user.email }}value="{{ user.email }}"{{/ user.email }}/>
{{#user.email}}value="{{user.email}}"{{/user.email}}/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="address">地址</label>
<input class="ItemInput" id="address" type="text" name="address" placeholder="请输入新地址"
{{# user.address }}value="{{ user.address }}"{{/ user.address }}/>
{{#user.address}}value="{{user.address}}"{{/user.address}}/>
</div>
<div class="TabFormItem">
<input class="ItemInput" id="gender_null" type="radio" name="gender" value="N"
{{# isGenderAsUnknown }}checked{{/ isGenderAsUnknown }} />
{{#isGenderAsUnknown}}checked{{/isGenderAsUnknown}} />
<label class="ItemName" for="gender_null">未知</label>
<input class="ItemInput" id="gender_male" type="radio" name="gender" value="M"
{{# isGenderAsMale }}checked{{/ isGenderAsMale }} />
{{#isGenderAsMale}}checked{{/isGenderAsMale}} />
<label class="ItemName" for="gender_male">男性</label>
<input class="ItemInput" id="gender_female" type="radio" name="gender" value="F"
{{# isGenderAsFemale }}checked{{/ isGenderAsFemale }} />
{{#isGenderAsFemale}}checked{{/isGenderAsFemale}} />
<label class="ItemName" for="gender_female">女性</label>
</div>
</div>
@ -95,7 +95,7 @@
</form>
</div>
{{> footer }}
{{>footer}}
</body>
</html>

View File

@ -3,35 +3,56 @@
<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="text/javascript" src="scripts/edit.js"></script>
<link type="image/x-icon" rel="icon" href="images/favicon.ico">
<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>
<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/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/form.css">
<!-- 页面特定的样式表 -->
<link type="text/css" rel="stylesheet" href="styles/edit.css">
<link type="text/css" rel="stylesheet/less" href="/styles/edit.less">
<!-- 外部小组件 -->
<script src="scripts/lib/anime.min.js"></script>
<script async src="scripts/lib/explosion.min.js"></script>
<script src="/scripts/lib/less.min.js"></script>
<script src="/scripts/lib/anime.min.js"></script>
<script async src="/scripts/lib/explosion.min.js"></script>
<!-- 实现更新与删除选项 -->
<script>
function getID(element) {
return element.parentElement.parentElement.getAttribute("id");
}
window.addEventListener("DOMContentLoaded", () => {
Array.from(document.getElementsByClassName("update")).forEach((v) => {
v.addEventListener("click", function () {
window.location.replace(`/editor?use={{using}}&action=updating&target=${getID(this)}`);
});
});
Array.from(document.getElementsByClassName("remove")).forEach((v) => {
v.addEventListener("click", function () {
window.location.replace(`/editor?use={{using}}&action=deleting&target=${getID(this)}`);
});
});
});
</script>
</head>
<body>
{{> header }}
{{>header}}
<!-- 页面内容 -->
<div id="Contents">
<div class="Title">
<div class="Tabs">
{{# tabs }}
<a href="/editor?use={{ first }}">{{ second }}</a>
{{/ tabs }}
{{#tabs}}
<a href="/editor?use={{first}}">{{second}}</a>
{{/tabs}}
</div>
<form class="Search" action="/editor" method="post">
@ -39,15 +60,15 @@
<label>
<select name="search_type">
{{# selects }}
<option value="{{ first }}">{{ second }}</option>
{{/ selects }}
{{#selects}}
<option value="{{first}}">{{second}}</option>
{{/selects}}
</select>
搜索
</label>
<label>
<input name="search_content" placeholder="请在此处输入你想要搜索的内容..."
{{# searching }}value="{{ searching }}"{{/ searching }}/>
{{#searching}}value="{{searching}}"{{/searching}}/>
</label>
<button type="submit">搜索</button>
</form>
@ -56,16 +77,27 @@
</div>
<div class="Editors">
{{# useUserEditor }}
{{> editor/user }}
{{/ useUserEditor }}
{{# useItemEditor }}
{{> editor/item }}
{{/ useItemEditor }}
{{#useUserEditor}}
{{>editor/user}}
{{/useUserEditor}}
{{#useItemEditor}}
{{>editor/item}}
{{/useItemEditor}}
</div>
<div class="Pages">
{{#pages}}
{{#first}}
<span>第 {{second}} 页</span>
{{/first}}
{{^first}}
<a href="/editor?use={{using}}&page={{second}}">第 {{second}} 页</a>
{{/first}}
{{/pages}}
</div>
</div>
{{> footer }}
{{>footer}}
</body>
</html>

View File

@ -2,38 +2,125 @@
<thead>
<tr>
<td>ID</td>
<td>用户名</td>
<td>帐户创建时间</td>
<td>最后登录时间</td>
<td>年龄</td>
<td>性别</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>
{{#data}}
<tr id="{{id}}">
<td>{{id}}</td>
<td>{{name}}</td>
<td>{{createTime}}</td>
<td>{{editTime}}</td>
<td>{{price}}</td>
<td>{{tags}}</td>
<td>
<button class="update">编辑</button>
<button class="remove">删除</button>
</td>
</tr>
{{/ Users }}
{{/data}}
</tbody>
</table>
<div class="EditPanel">
<!-- <iframe id="Panel" class="Panel" name="panel"></iframe>-->
{{#isNothing}}
<form class="TabForm" action="/editor" method="post">
<h2>请在左侧列表中选择需要进行的操作!</h2>
<input type="hidden" name="use" value="item"/>
<input type="hidden" name="action" value="creating"/>
<button type="submit">或者点击此处新建一个商品!</button>
</form>
{{/isNothing}}
{{#isCreating}}
<form class="TabForm" action="/action/edit/item/create" method="post" enctype="multipart/form-data">
<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="price">价格</label>
<input class="ItemInput" id="price" type="number" name="price" placeholder="请输入价格" required/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="description">详情</label>
<input class="ItemInput" id="description" type="text" name="description" placeholder="请输入详情"/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="tag">标签</label>
<input class="ItemInput" id="tag" type="text" name="tag" placeholder="请输入标签,以空格隔开!"/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="picture">图片</label>
<input class="ItemInput" id="picture" type="file" name="picture" placeholder="请选择图片" required/>
</div>
</div>
<div class="TabButtons">
<button class="TabButton" type="reset">重置</button>
<button class="TabButton" type="submit">创建</button>
</div>
</form>
{{/isCreating}}
{{#isUpdating}}
<form class="TabForm" action="/action/edit/item/update/{{target.id}}" method="post" enctype="multipart/form-data">
<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="请输入商品名"
{{#target.name}}value="{{target.name}}"{{/target.name}} required/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="price">价格</label>
<input class="ItemInput" id="price" type="number" name="price" placeholder="请输入价格"
{{#target.price}}value="{{target.price}}"{{/target.price}} required/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="description">详情</label>
<input class="ItemInput" id="description" type="text" name="description" placeholder="请输入详情"
{{#target.description}}value="{{target.description}}"{{/target.description}}/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="tag">标签</label>
<input class="ItemInput" id="tag" type="text" name="tag" placeholder="请输入标签,以空格隔开!"
{{#target.tags}}value="{{target.tags}}"{{/target.tags}}/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="picture">图片</label>
<input class="ItemInput" id="picture" type="file" name="picture" placeholder="请选择图片"/>
</div>
</div>
<div class="TabButtons">
<button class="TabButton" type="submit">更新</button>
</div>
</form>
{{/isUpdating}}
{{#isDeleting}}
<form class="TabForm" action="/action/edit/item/delete/{{target.id}}" method="post">
<h2>确定要删除商品 {{target.name}} 吗?</h2>
<button class="TabButton" type="submit">删除</button>
</form>
{{/isDeleting}}
</div>

View File

@ -15,27 +15,175 @@
</tr>
</thead>
<tbody>
{{# data }}
<tr id="{{ id }}">
<td>{{ id }}</td>
<td>{{ name }}</td>
<td>{{ createTime }}</td>
<td>{{ loginTime }}</td>
<td>{{# age }}{{ age }}{{/ age }}</td>
<td>{{# gender }}{{ gender }}{{/ gender }}</td>
<td>{{# phone }}{{ phone }}{{/ phone }}</td>
<td>{{# email }}{{ email }}{{/ email }}</td>
<td>{{# address }}{{ address }}{{/ address }}</td>
<td>{{# isAdmin }}是{{/ isAdmin }}{{^ isAdmin }}否{{/ isAdmin }}</td>
{{#data}}
<tr id="{{id}}">
<td>{{id}}</td>
<td>{{name}}</td>
<td>{{createTime}}</td>
<td>{{loginTime}}</td>
<td>{{#age}}{{age}}{{/age}}</td>
<td>{{#gender}}{{gender}}{{/gender}}</td>
<td>{{#phone}}{{phone}}{{/phone}}</td>
<td>{{#email}}{{email}}{{/email}}</td>
<td>{{#address}}{{address}}{{/address}}</td>
<td>{{#isAdmin}}是{{/isAdmin}}{{^isAdmin}}否{{/isAdmin}}</td>
<td>
<button class="update">编辑</button>
<button class="remove">删除</button>
</td>
</tr>
{{/ data }}
{{/data}}
</tbody>
</table>
<div class="EditPanel">
<!-- <iframe id="Panel" class="Panel" name="panel"></iframe>-->
{{#isNothing}}
<form class="TabForm" action="/editor" method="post">
<h2>请在左侧列表中选择需要进行的操作!</h2>
<input type="hidden" name="use" value="user"/>
<input type="hidden" name="action" value="creating"/>
<button type="submit">或者点击此处新建一个用户!</button>
</form>
{{/isNothing}}
{{#isCreating}}
<form class="TabForm" action="/action/edit/user/create" 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 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 class="TabFormItem">
<input class="ItemInput" id="admin_false" type="radio" name="is_admin" value="false" checked/>
<label class="ItemName" for="admin_false">非管理员</label>
<input class="ItemInput" id="gender_male" type="radio" name="is_admin" value="true"/>
<label class="ItemName" for="gender_male">为管理员</label>
</div>
</div>
<div class="TabButtons">
<button class="TabButton" type="reset">重置</button>
<button class="TabButton" type="submit">创建</button>
</div>
</form>
{{/isCreating}}
{{#isUpdating}}
<form class="TabForm" action="/action/edit/user/update/{{target.id}}" 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="请输入新用户名"
value="{{target.name}}"/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="password">密码</label>
<input class="ItemInput" id="password" type="password" name="password" placeholder="请输入新密码"/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="age">年龄</label>
<input class="ItemInput" id="age" type="number" name="age" placeholder="请输入新年龄"
{{#target.age}}value="{{target.age}}"{{/target.age}}/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="phone">手机号码</label>
<input class="ItemInput" id="phone" type="tel" name="phone" placeholder="请输入新手机号"
{{#target.phone}}value="{{target.phone}}{{/target.phone}}"/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="email">邮箱</label>
<input class="ItemInput" id="email" type="email" name="email" placeholder="请输入新邮箱"
{{#target.email}}value="{{target.email}}"{{/target.email}}/>
</div>
<div class="TabFormItem">
<label class="ItemName" for="address">地址</label>
<input class="ItemInput" id="address" type="text" name="address" placeholder="请输入新地址"
{{#target.address}}value="{{target.address}}"{{/target.address}}/>
</div>
<div class="TabFormItem">
<input class="ItemInput" id="gender_null" type="radio" name="gender" value="N"
{{#isGenderAsUnknown}}checked{{/isGenderAsUnknown}} />
<label class="ItemName" for="gender_null">未知</label>
<input class="ItemInput" id="gender_male" type="radio" name="gender" value="M"
{{#isGenderAsMale}}checked{{/isGenderAsMale}} />
<label class="ItemName" for="gender_male">男性</label>
<input class="ItemInput" id="gender_female" type="radio" name="gender" value="F"
{{#isGenderAsFemale}}checked{{/isGenderAsFemale}} />
<label class="ItemName" for="gender_female">女性</label>
</div>
<div class="TabFormItem">
<input class="ItemInput" id="admin_false" type="radio" name="is_admin" value="false"
{{^target.isAdmin}}checked{{/target.isAdmin}} />
<label class="ItemName" for="admin_false">非管理员</label>
<input class="ItemInput" id="gender_male" type="radio" name="is_admin" value="true"
{{#target.isAdmin}}checked{{/target.isAdmin}} />
<label class="ItemName" for="gender_male">为管理员</label>
</div>
</div>
<div class="TabButtons">
<button class="TabButton" type="submit">更新</button>
</div>
</form>
{{/isUpdating}}
{{#isDeleting}}
<form class="TabForm" action="/action/edit/user/delete/{{target.id}}" method="post">
<h2>确定要删除用户 {{target.name}} 吗?</h2>
<button class="TabButton" type="submit">删除</button>
</form>
{{/isDeleting}}
</div>

View File

@ -3,44 +3,44 @@
<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">
<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/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">
<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>
<script src="/scripts/lib/anime.min.js"></script>
<script async src="/scripts/lib/explosion.min.js"></script>
<!-- 自动跳转 -->
{{# redirect }}
<meta http-equiv="refresh" content="3;url={{ redirect }}">
{{/ redirect }}
{{#redirect}}
<meta http-equiv="refresh" content="3;url={{redirect}}">
{{/redirect}}
</head>
<body>
{{> header }}
{{>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 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 }}
{{>footer}}
</body>
</html>

View File

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

View File

@ -15,16 +15,21 @@
</div>
<div class="List Blank"></div>
{{#user}}
<div class="List Button Link" {{#isCart}}this{{/isCart}}{{^isCart}}href="/cart"{{/isCart}}><span class="Text">购物车</span></div>
<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" {{#isEditor}}this{{/isEditor}}{{^isEditor}}href="/editor"{{/isEditor}}><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" {{#isAccount}}this{{/isAccount}}{{^isAccount}}href="/account"{{/isAccount}}><span class="Text">账户</span></div>
<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>
<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>

View File

@ -3,29 +3,29 @@
<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">
<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/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">
<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>
<script src="/scripts/lib/anime.min.js"></script>
<script async src="/scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header }}
{{>header}}
<!-- 页面内容 -->
<div id="Contents">
@ -60,7 +60,7 @@
</div>
</div>
{{> footer }}
{{>footer}}
</body>
</html>

View File

@ -3,36 +3,35 @@
<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">
<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/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/item.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>
<script src="/scripts/lib/anime.min.js"></script>
<script async src="/scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header }}
{{>header}}
<!-- 页面内容 -->
<div id="Contents">
<div class="Item">
<div class="Picture">
<img alt="商品图片" src=""/>
<img alt="商品图片" src="{{item.picture}}"/>
</div>
<div class="Infos">
<span class="Title"></span>
@ -62,7 +61,7 @@
</div>
</div>
{{> footer }}
{{>footer}}
</body>
</html>

View File

@ -3,30 +3,30 @@
<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">
<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/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">
<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>
<script src="/scripts/lib/anime.min.js"></script>
<script async src="/scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header}}
{{>header}}
<!-- 页面内容 -->
<div id="Contents">
@ -52,7 +52,7 @@
</form>
</div>
{{> footer}}
{{>footer}}
</body>
</html>

View File

@ -3,30 +3,30 @@
<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>
<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/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">
<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>
<script src="/scripts/lib/anime.min.js"></script>
<script async src="/scripts/lib/explosion.min.js"></script>
</head>
<body>
{{> header }}
{{>header}}
<!-- 页面内容 -->
<div id="Contents">
@ -57,7 +57,7 @@
</div>
<div class="TabFormItem">
<label class="ItemName" for="phone">邮箱</label>
<label class="ItemName" for="phone">手机号码</label>
<input class="ItemInput" id="phone" type="text" name="phone" placeholder="请输入手机号"/>
</div>
@ -67,8 +67,8 @@
</div>
<div class="TabFormItem">
<label class="ItemName" for="address">邮箱</label>
<input class="ItemInput" id="address" type="text" name="address" placeholder="请输入邮箱"/>
<label class="ItemName" for="address">地址</label>
<input class="ItemInput" id="address" type="text" name="address" placeholder="请输入地址"/>
</div>
<div class="TabFormItem">
@ -88,7 +88,7 @@
</form>
</div>
{{> footer }}
{{>footer}}
</body>
</html>

View File

@ -1,7 +0,0 @@
{{> header}}
<div>
<label>用户名: {{userName}}</label>
</div>
{{> footer}}