|
|
@@ -10,6 +10,7 @@ import javafx.scene.control.*;
|
|
|
import javafx.scene.control.cell.PropertyValueFactory;
|
|
|
import javafx.scene.layout.*;
|
|
|
import javafx.geometry.Pos;
|
|
|
+import javafx.stage.Modality;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import space.anyi.client.App;
|
|
|
import space.anyi.client.service.AiService;
|
|
|
@@ -20,6 +21,7 @@ import space.anyi.client.service.UserService;
|
|
|
import space.anyi.client.util.LoginUserHolder;
|
|
|
import space.anyi.common.dto.PageResult;
|
|
|
import space.anyi.common.dto.R;
|
|
|
+import space.anyi.common.dto.BookDetailDTO;
|
|
|
import space.anyi.common.entity.Book;
|
|
|
import space.anyi.common.entity.TransactionRecord;
|
|
|
import space.anyi.common.entity.User;
|
|
|
@@ -30,6 +32,7 @@ import space.anyi.common.dto.UserTransactionDTO;
|
|
|
import space.anyi.common.dto.DeptDiscountDTO;
|
|
|
import space.anyi.common.dto.SalesRecordDTO;
|
|
|
import space.anyi.common.dto.StatisticsSummary;
|
|
|
+import space.anyi.common.dto.TransactionDetailDTO;
|
|
|
import java.io.IOException;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.util.List;
|
|
|
@@ -52,7 +55,15 @@ public class MainController {
|
|
|
@FXML private VBox profilePane;
|
|
|
@FXML private VBox sellerPane;
|
|
|
@FXML private ScrollPane statsPane;
|
|
|
- @FXML private ScrollPane adminPane;
|
|
|
+ @FXML private SplitPane adminPane;
|
|
|
+ @FXML private StackPane adminContentArea;
|
|
|
+
|
|
|
+ // Admin sub-panes
|
|
|
+ @FXML private VBox adminUserPane;
|
|
|
+ @FXML private VBox adminBookPane;
|
|
|
+ @FXML private VBox adminPendingPane;
|
|
|
+ @FXML private VBox adminTransPane;
|
|
|
+ @FXML private VBox adminAnalysisPane;
|
|
|
|
|
|
// Browse tab
|
|
|
@FXML private TextField searchField;
|
|
|
@@ -129,16 +140,6 @@ public class MainController {
|
|
|
|
|
|
// Admin tab
|
|
|
@FXML private TableView<User> userTable;
|
|
|
- @FXML private TitledPane userFormPane;
|
|
|
- @FXML private Button saveUserBtn;
|
|
|
- @FXML private TextField adminUsername;
|
|
|
- @FXML private PasswordField adminPassword;
|
|
|
- @FXML private TextField adminNickname;
|
|
|
- @FXML private TextField adminEmail;
|
|
|
- @FXML private TextField adminPhone;
|
|
|
- @FXML private TextField adminDept;
|
|
|
- @FXML private ComboBox<String> adminRole;
|
|
|
- @FXML private CheckBox adminSeller;
|
|
|
@FXML private Button adminUserPrevBtn;
|
|
|
@FXML private Button adminUserNextBtn;
|
|
|
@FXML private Label adminUserPageLabel;
|
|
|
@@ -152,27 +153,29 @@ public class MainController {
|
|
|
@FXML private TableColumn<User, Integer> userCreditCol;
|
|
|
@FXML private TableColumn<User, Integer> userRoleCol;
|
|
|
@FXML private TableColumn<User, Integer> userSellerCol;
|
|
|
- @FXML private TableView<Book> adminBookTable;
|
|
|
- @FXML private TableColumn<Book, Integer> adminBookIdCol;
|
|
|
- @FXML private TableColumn<Book, String> adminBookTitleCol;
|
|
|
- @FXML private TableColumn<Book, String> adminBookAuthorCol;
|
|
|
- @FXML private TableColumn<Book, String> adminBookCategoryCol;
|
|
|
- @FXML private TableColumn<Book, java.math.BigDecimal> adminBookPriceCol;
|
|
|
- @FXML private TableColumn<Book, Integer> adminBookStockCol;
|
|
|
- @FXML private TableColumn<Book, Integer> adminBookSellerCol;
|
|
|
- @FXML private TableView<Book> pendingBookTable;
|
|
|
- @FXML private TableColumn<Book, Integer> pendingBookIdCol;
|
|
|
- @FXML private TableColumn<Book, String> pendingBookTitleCol;
|
|
|
- @FXML private TableColumn<Book, String> pendingBookAuthorCol;
|
|
|
- @FXML private TableColumn<Book, Integer> pendingBookSellerCol;
|
|
|
- @FXML private TableColumn<Book, java.math.BigDecimal> pendingBookPriceCol;
|
|
|
- @FXML private TableView<TransactionRecord> allTransTable;
|
|
|
- @FXML private TableColumn<TransactionRecord, Integer> allTransIdCol;
|
|
|
- @FXML private TableColumn<TransactionRecord, Integer> allTransBookIdCol;
|
|
|
- @FXML private TableColumn<TransactionRecord, Integer> allTransBuyerIdCol;
|
|
|
- @FXML private TableColumn<TransactionRecord, Integer> allTransNumCol;
|
|
|
- @FXML private TableColumn<TransactionRecord, java.math.BigDecimal> allTransPriceCol;
|
|
|
- @FXML private TableColumn<TransactionRecord, String> allTransTimeCol;
|
|
|
+ @FXML private TableColumn<User, Void> userActionCol;
|
|
|
+ @FXML private TableView<BookDetailDTO> adminBookTable;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, Integer> adminBookIdCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, String> adminBookTitleCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, String> adminBookAuthorCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, String> adminBookCategoryCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, java.math.BigDecimal> adminBookPriceCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, Integer> adminBookStockCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, String> adminBookSellerCol;
|
|
|
+ @FXML private TableView<BookDetailDTO> pendingBookTable;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, Integer> pendingBookIdCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, String> pendingBookTitleCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, String> pendingBookAuthorCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, String> pendingBookSellerCol;
|
|
|
+ @FXML private TableColumn<BookDetailDTO, java.math.BigDecimal> pendingBookPriceCol;
|
|
|
+ @FXML private TableView<TransactionDetailDTO> allTransTable;
|
|
|
+ @FXML private TableColumn<TransactionDetailDTO, Integer> allTransIdCol;
|
|
|
+ @FXML private TableColumn<TransactionDetailDTO, String> allTransBookTitleCol;
|
|
|
+ @FXML private TableColumn<TransactionDetailDTO, String> allTransBuyerNameCol;
|
|
|
+ @FXML private TableColumn<TransactionDetailDTO, String> allTransSellerNameCol;
|
|
|
+ @FXML private TableColumn<TransactionDetailDTO, Integer> allTransNumCol;
|
|
|
+ @FXML private TableColumn<TransactionDetailDTO, java.math.BigDecimal> allTransPriceCol;
|
|
|
+ @FXML private TableColumn<TransactionDetailDTO, java.time.LocalDateTime> allTransTimeCol;
|
|
|
@FXML private Button generateBtn;
|
|
|
@FXML private TextArea analysisResult;
|
|
|
|
|
|
@@ -184,7 +187,6 @@ public class MainController {
|
|
|
|
|
|
private Book selectedBook;
|
|
|
private Book editingBook;
|
|
|
- private User editingUser;
|
|
|
|
|
|
@FXML private Button prevPageBtn;
|
|
|
@FXML private Button nextPageBtn;
|
|
|
@@ -278,12 +280,27 @@ public class MainController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void switchAdminPane(VBox pane) {
|
|
|
+ for (javafx.scene.Node child : adminContentArea.getChildren()) {
|
|
|
+ child.setVisible(false);
|
|
|
+ child.setManaged(false);
|
|
|
+ }
|
|
|
+ pane.setVisible(true);
|
|
|
+ pane.setManaged(true);
|
|
|
+ }
|
|
|
+
|
|
|
@FXML private void handleNavBrowse() { switchPane(browsePane); }
|
|
|
@FXML private void handleNavTrans() { switchPane(transPane); handleLoadTransactions(); }
|
|
|
@FXML private void handleNavProfile() { switchPane(profilePane); }
|
|
|
@FXML private void handleNavSeller() { switchPane(sellerPane); handleLoadMyBooks(); }
|
|
|
@FXML private void handleNavStats() { switchPane(statsPane); handleLoadStatistics(); }
|
|
|
- @FXML private void handleNavAdmin() { switchPane(adminPane); handleLoadAllUsers(); handleLoadAllBooksAdmin(); handleLoadPendingBooks(); handleLoadAllTransactions(); }
|
|
|
+ @FXML private void handleNavAdmin() { switchPane(adminPane); switchAdminPane(adminUserPane); handleLoadAllUsers(); }
|
|
|
+
|
|
|
+ @FXML private void handleAdminNavUsers() { switchAdminPane(adminUserPane); handleLoadAllUsers(); }
|
|
|
+ @FXML private void handleAdminNavBooks() { switchAdminPane(adminBookPane); handleLoadAllBooksAdmin(); }
|
|
|
+ @FXML private void handleAdminNavPending() { switchAdminPane(adminPendingPane); handleLoadPendingBooks(); }
|
|
|
+ @FXML private void handleAdminNavTransactions() { switchAdminPane(adminTransPane); handleLoadAllTransactions(); }
|
|
|
+ @FXML private void handleAdminNavAnalysis() { switchAdminPane(adminAnalysisPane); }
|
|
|
|
|
|
private void loadSubPane(String path) throws IOException {
|
|
|
FXMLLoader loader = new FXMLLoader(getClass().getResource(path));
|
|
|
@@ -897,6 +914,60 @@ public class MainController {
|
|
|
userCreditCol.setCellValueFactory(new PropertyValueFactory<>("credit"));
|
|
|
userRoleCol.setCellValueFactory(new PropertyValueFactory<>("role"));
|
|
|
userSellerCol.setCellValueFactory(new PropertyValueFactory<>("isSeller"));
|
|
|
+ userRoleCol.setCellFactory(col -> new TableCell<User, Integer>() {
|
|
|
+ @Override
|
|
|
+ protected void updateItem(Integer item, boolean empty) {
|
|
|
+ super.updateItem(item, empty);
|
|
|
+ if (empty || item == null) {
|
|
|
+ setText(null);
|
|
|
+ } else {
|
|
|
+ setText(item == 1 ? "管理员" : "学生");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ userSellerCol.setCellFactory(col -> new TableCell<User, Integer>() {
|
|
|
+ @Override
|
|
|
+ protected void updateItem(Integer item, boolean empty) {
|
|
|
+ super.updateItem(item, empty);
|
|
|
+ if (empty || item == null) {
|
|
|
+ setText(null);
|
|
|
+ } else {
|
|
|
+ setText(item == 1 ? "是" : "否");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ userActionCol.setCellFactory(col -> new TableCell<User, Void>() {
|
|
|
+ private final Button editBtn = new Button("编辑");
|
|
|
+ private final Button delBtn = new Button("删除");
|
|
|
+ private final HBox box = new HBox(6, editBtn, delBtn);
|
|
|
+ {
|
|
|
+ editBtn.getStyleClass().addAll("btn", "btn-warning");
|
|
|
+ editBtn.setStyle("-fx-padding: 4px 12px; -fx-font-size: 12px;");
|
|
|
+ delBtn.getStyleClass().addAll("btn", "btn-danger");
|
|
|
+ delBtn.setStyle("-fx-padding: 4px 12px; -fx-font-size: 12px;");
|
|
|
+ editBtn.setOnAction(e -> {
|
|
|
+ User u = getTableView().getItems().get(getIndex());
|
|
|
+ showUserDialog(u);
|
|
|
+ });
|
|
|
+ delBtn.setOnAction(e -> {
|
|
|
+ User u = getTableView().getItems().get(getIndex());
|
|
|
+ if (!confirm("确认删除用户「" + u.getUsername() + "」?此操作不可恢复。")) return;
|
|
|
+ R<Void> r = userService.delete(u.getUserid());
|
|
|
+ if (r.getCode() == 200) {
|
|
|
+ showInfo("用户已删除");
|
|
|
+ handleLoadAllUsers();
|
|
|
+ } else {
|
|
|
+ showAlert(r.getMessage());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ protected void updateItem(Void item, boolean empty) {
|
|
|
+ super.updateItem(item, empty);
|
|
|
+ setGraphic(empty ? null : box);
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
adminBookIdCol.setCellValueFactory(new PropertyValueFactory<>("bookId"));
|
|
|
adminBookTitleCol.setCellValueFactory(new PropertyValueFactory<>("title"));
|
|
|
@@ -904,22 +975,38 @@ public class MainController {
|
|
|
adminBookCategoryCol.setCellValueFactory(new PropertyValueFactory<>("category"));
|
|
|
adminBookPriceCol.setCellValueFactory(new PropertyValueFactory<>("sellingPrice"));
|
|
|
adminBookStockCol.setCellValueFactory(new PropertyValueFactory<>("stock"));
|
|
|
- adminBookSellerCol.setCellValueFactory(new PropertyValueFactory<>("sellerId"));
|
|
|
+ adminBookSellerCol.setCellValueFactory(new PropertyValueFactory<>("sellerName"));
|
|
|
|
|
|
pendingBookIdCol.setCellValueFactory(new PropertyValueFactory<>("bookId"));
|
|
|
pendingBookTitleCol.setCellValueFactory(new PropertyValueFactory<>("title"));
|
|
|
pendingBookAuthorCol.setCellValueFactory(new PropertyValueFactory<>("author"));
|
|
|
- pendingBookSellerCol.setCellValueFactory(new PropertyValueFactory<>("sellerId"));
|
|
|
+ pendingBookSellerCol.setCellValueFactory(new PropertyValueFactory<>("sellerName"));
|
|
|
pendingBookPriceCol.setCellValueFactory(new PropertyValueFactory<>("sellingPrice"));
|
|
|
|
|
|
allTransIdCol.setCellValueFactory(new PropertyValueFactory<>("transId"));
|
|
|
- allTransBookIdCol.setCellValueFactory(new PropertyValueFactory<>("bookId"));
|
|
|
- allTransBuyerIdCol.setCellValueFactory(new PropertyValueFactory<>("buyerId"));
|
|
|
+ allTransBookTitleCol.setCellValueFactory(new PropertyValueFactory<>("bookTitle"));
|
|
|
+ allTransBuyerNameCol.setCellValueFactory(new PropertyValueFactory<>("buyerName"));
|
|
|
+ allTransSellerNameCol.setCellValueFactory(new PropertyValueFactory<>("sellerName"));
|
|
|
allTransNumCol.setCellValueFactory(new PropertyValueFactory<>("transactionNum"));
|
|
|
allTransPriceCol.setCellValueFactory(new PropertyValueFactory<>("transactionPrice"));
|
|
|
allTransTimeCol.setCellValueFactory(new PropertyValueFactory<>("transactionTime"));
|
|
|
+ java.time.format.DateTimeFormatter dtf = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
+ allTransTimeCol.setCellFactory(col -> new TableCell<TransactionDetailDTO, java.time.LocalDateTime>() {
|
|
|
+ @Override
|
|
|
+ protected void updateItem(java.time.LocalDateTime item, boolean empty) {
|
|
|
+ super.updateItem(item, empty);
|
|
|
+ if (empty || item == null) {
|
|
|
+ setText(null);
|
|
|
+ } else {
|
|
|
+ setText(item.format(dtf));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- adminRole.getItems().addAll("学生", "管理员");
|
|
|
+ userTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
|
|
+ adminBookTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
|
|
+ pendingBookTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
|
|
+ allTransTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
|
|
}
|
|
|
|
|
|
@FXML
|
|
|
@@ -952,18 +1039,18 @@ public class MainController {
|
|
|
showAlert("请先选择要编辑的用户");
|
|
|
return;
|
|
|
}
|
|
|
- editingUser = sel;
|
|
|
- adminUsername.setText(sel.getUsername());
|
|
|
- adminPassword.setText(sel.getPassword());
|
|
|
- adminNickname.setText(sel.getNickname());
|
|
|
- adminEmail.setText(sel.getEmail());
|
|
|
- adminPhone.setText(sel.getPhone());
|
|
|
- adminDept.setText(sel.getDept());
|
|
|
- adminRole.getSelectionModel().select(sel.getRole() != null ? sel.getRole() : 0);
|
|
|
- adminSeller.setSelected(sel.getIsSeller() != null && sel.getIsSeller() == 1);
|
|
|
- userFormPane.setText("编辑用户");
|
|
|
- saveUserBtn.setText("保存修改");
|
|
|
- userFormPane.setExpanded(true);
|
|
|
+ showUserDialog(sel);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean confirm(String message) {
|
|
|
+ Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
|
|
+ alert.setTitle("确认操作");
|
|
|
+ alert.setHeaderText(null);
|
|
|
+ Label label = new Label(message);
|
|
|
+ label.setWrapText(true);
|
|
|
+ alert.getDialogPane().setContent(label);
|
|
|
+ alert.getButtonTypes().setAll(ButtonType.CANCEL, ButtonType.OK);
|
|
|
+ return alert.showAndWait().map(b -> b == ButtonType.OK).orElse(false);
|
|
|
}
|
|
|
|
|
|
@FXML
|
|
|
@@ -973,6 +1060,7 @@ public class MainController {
|
|
|
showAlert("请先选择要重置密码的用户");
|
|
|
return;
|
|
|
}
|
|
|
+ if (!confirm("确认将用户「" + sel.getUsername() + "」的密码重置为 123456?")) return;
|
|
|
sel.setPassword("123456");
|
|
|
R<User> result = userService.update(sel.getUserid(), sel);
|
|
|
if (result.getCode() == 200) {
|
|
|
@@ -1011,66 +1099,8 @@ public class MainController {
|
|
|
}
|
|
|
|
|
|
@FXML
|
|
|
- private void handleToggleUserForm() {
|
|
|
- userFormPane.setExpanded(!userFormPane.isExpanded());
|
|
|
- if (userFormPane.isExpanded()) {
|
|
|
- clearUserForm();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @FXML
|
|
|
- private void handleCancelUserForm() {
|
|
|
- clearUserForm();
|
|
|
- }
|
|
|
-
|
|
|
- @FXML
|
|
|
- private void handleSaveUser() {
|
|
|
- try {
|
|
|
- String username = adminUsername.getText().trim();
|
|
|
- String password = adminPassword.getText().trim();
|
|
|
- if (username.isEmpty() || password.isEmpty()) {
|
|
|
- showAlert("用户名和密码为必填项");
|
|
|
- return;
|
|
|
- }
|
|
|
- if (editingUser != null) {
|
|
|
- editingUser.setUsername(username);
|
|
|
- editingUser.setPassword(password);
|
|
|
- editingUser.setNickname(adminNickname.getText().trim());
|
|
|
- editingUser.setEmail(adminEmail.getText().trim());
|
|
|
- editingUser.setPhone(adminPhone.getText().trim());
|
|
|
- editingUser.setDept(adminDept.getText().trim());
|
|
|
- editingUser.setRole(adminRole.getSelectionModel().getSelectedIndex());
|
|
|
- editingUser.setIsSeller(adminSeller.isSelected() ? 1 : 0);
|
|
|
- R<User> result = userService.update(editingUser.getUserid(), editingUser);
|
|
|
- if (result.getCode() == 200) {
|
|
|
- showInfo("用户信息已更新");
|
|
|
- clearUserForm();
|
|
|
- handleLoadAllUsers();
|
|
|
- } else {
|
|
|
- showAlert(result.getMessage());
|
|
|
- }
|
|
|
- } else {
|
|
|
- RegisterRequest req = new RegisterRequest();
|
|
|
- req.setUsername(username);
|
|
|
- req.setPassword(password);
|
|
|
- req.setNickname(adminNickname.getText().trim());
|
|
|
- req.setEmail(adminEmail.getText().trim());
|
|
|
- req.setPhone(adminPhone.getText().trim());
|
|
|
- req.setDept(adminDept.getText().trim());
|
|
|
- req.setRole(adminRole.getSelectionModel().getSelectedIndex());
|
|
|
- req.setIsSeller(adminSeller.isSelected() ? 1 : 0);
|
|
|
- R<User> result = userService.register(req);
|
|
|
- if (result.getCode() == 200) {
|
|
|
- showInfo("用户已添加");
|
|
|
- clearUserForm();
|
|
|
- handleLoadAllUsers();
|
|
|
- } else {
|
|
|
- showAlert(result.getMessage());
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- showAlert("输入无效:" + e.getMessage());
|
|
|
- }
|
|
|
+ private void handleAddUser() {
|
|
|
+ showUserDialog(null);
|
|
|
}
|
|
|
|
|
|
@FXML
|
|
|
@@ -1080,6 +1110,7 @@ public class MainController {
|
|
|
showAlert("请选择要删除的用户");
|
|
|
return;
|
|
|
}
|
|
|
+ if (!confirm("确认删除用户「" + sel.getUsername() + "」?此操作不可恢复。")) return;
|
|
|
R<Void> result = userService.delete(sel.getUserid());
|
|
|
if (result.getCode() == 200) {
|
|
|
showInfo("用户已删除");
|
|
|
@@ -1091,7 +1122,7 @@ public class MainController {
|
|
|
|
|
|
@FXML
|
|
|
private void handleLoadAllBooksAdmin() {
|
|
|
- R<List<Book>> result = bookService.listAll();
|
|
|
+ R<List<BookDetailDTO>> result = bookService.listAll();
|
|
|
if (result.getCode() == 200 && result.getData() != null) {
|
|
|
adminBookTable.setItems(FXCollections.observableArrayList(result.getData()));
|
|
|
}
|
|
|
@@ -1099,11 +1130,12 @@ public class MainController {
|
|
|
|
|
|
@FXML
|
|
|
private void handleDeleteBookAdmin() {
|
|
|
- Book sel = adminBookTable.getSelectionModel().getSelectedItem();
|
|
|
+ BookDetailDTO sel = adminBookTable.getSelectionModel().getSelectedItem();
|
|
|
if (sel == null) {
|
|
|
showAlert("请选择要删除的书籍");
|
|
|
return;
|
|
|
}
|
|
|
+ if (!confirm("确认删除书籍《" + sel.getTitle() + "》?此操作不可恢复。")) return;
|
|
|
R<Void> result = bookService.delete(sel.getBookId());
|
|
|
if (result.getCode() == 200) {
|
|
|
showInfo("书籍已删除");
|
|
|
@@ -1115,7 +1147,7 @@ public class MainController {
|
|
|
|
|
|
@FXML
|
|
|
private void handleLoadPendingBooks() {
|
|
|
- R<List<Book>> result = bookService.getPendingBooks();
|
|
|
+ R<List<BookDetailDTO>> result = bookService.getPendingBooks();
|
|
|
if (result.getCode() == 200 && result.getData() != null) {
|
|
|
pendingBookTable.setItems(FXCollections.observableArrayList(result.getData()));
|
|
|
}
|
|
|
@@ -1123,7 +1155,7 @@ public class MainController {
|
|
|
|
|
|
@FXML
|
|
|
private void handleApproveBook() {
|
|
|
- Book sel = pendingBookTable.getSelectionModel().getSelectedItem();
|
|
|
+ BookDetailDTO sel = pendingBookTable.getSelectionModel().getSelectedItem();
|
|
|
if (sel == null) {
|
|
|
showAlert("请先选择待审核的书籍");
|
|
|
return;
|
|
|
@@ -1139,7 +1171,7 @@ public class MainController {
|
|
|
|
|
|
@FXML
|
|
|
private void handleRejectBook() {
|
|
|
- Book sel = pendingBookTable.getSelectionModel().getSelectedItem();
|
|
|
+ BookDetailDTO sel = pendingBookTable.getSelectionModel().getSelectedItem();
|
|
|
if (sel == null) {
|
|
|
showAlert("请先选择待审核的书籍");
|
|
|
return;
|
|
|
@@ -1155,7 +1187,7 @@ public class MainController {
|
|
|
|
|
|
@FXML
|
|
|
private void handleLoadAllTransactions() {
|
|
|
- R<PageResult<TransactionRecord>> result = transactionService.listAll(adminTransPage, ADMIN_pageSize);
|
|
|
+ R<PageResult<TransactionDetailDTO>> result = transactionService.listAll(adminTransPage, ADMIN_pageSize);
|
|
|
if (result.getCode() == 200 && result.getData() != null && result.getData().getRecords() != null) {
|
|
|
allTransTable.setItems(FXCollections.observableArrayList(result.getData().getRecords()));
|
|
|
long total = result.getData().getTotal();
|
|
|
@@ -1178,11 +1210,12 @@ public class MainController {
|
|
|
|
|
|
@FXML
|
|
|
private void handleDeleteTransaction() {
|
|
|
- TransactionRecord sel = allTransTable.getSelectionModel().getSelectedItem();
|
|
|
+ TransactionDetailDTO sel = allTransTable.getSelectionModel().getSelectedItem();
|
|
|
if (sel == null) {
|
|
|
showAlert("请选择要删除的交易");
|
|
|
return;
|
|
|
}
|
|
|
+ if (!confirm("确认删除交易 ID=" + sel.getTransId() + "?此操作不可恢复。")) return;
|
|
|
R<Void> result = transactionService.delete(sel.getTransId());
|
|
|
if (result.getCode() == 200) {
|
|
|
showInfo("交易已删除");
|
|
|
@@ -1248,19 +1281,122 @@ public class MainController {
|
|
|
bookFormPane.setExpanded(false);
|
|
|
}
|
|
|
|
|
|
- private void clearUserForm() {
|
|
|
- editingUser = null;
|
|
|
- adminUsername.clear();
|
|
|
- adminPassword.clear();
|
|
|
- adminNickname.clear();
|
|
|
- adminEmail.clear();
|
|
|
- adminPhone.clear();
|
|
|
- adminDept.clear();
|
|
|
- adminRole.getSelectionModel().select(0);
|
|
|
- adminSeller.setSelected(false);
|
|
|
- userFormPane.setText("添加用户");
|
|
|
- saveUserBtn.setText("保存");
|
|
|
- userFormPane.setExpanded(false);
|
|
|
+ private void showUserDialog(User user) {
|
|
|
+ boolean isNew = (user == null);
|
|
|
+ Dialog<User> dialog = new Dialog<>();
|
|
|
+ dialog.setTitle(isNew ? "添加用户" : "编辑用户");
|
|
|
+ dialog.initModality(Modality.NONE);
|
|
|
+ dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
|
|
|
+ dialog.getDialogPane().setPrefWidth(560);
|
|
|
+
|
|
|
+ GridPane grid = new GridPane();
|
|
|
+ grid.setHgap(12);
|
|
|
+ grid.setVgap(10);
|
|
|
+ grid.setPadding(new javafx.geometry.Insets(20));
|
|
|
+ ColumnConstraints col1 = new ColumnConstraints(60);
|
|
|
+ ColumnConstraints col2 = new ColumnConstraints(190, 190, Double.MAX_VALUE);
|
|
|
+ ColumnConstraints col3 = new ColumnConstraints(60);
|
|
|
+ ColumnConstraints col4 = new ColumnConstraints(190, 190, Double.MAX_VALUE);
|
|
|
+ grid.getColumnConstraints().addAll(col1, col2, col3, col4);
|
|
|
+
|
|
|
+ TextField usernameField = new TextField();
|
|
|
+ usernameField.setPromptText("必填");
|
|
|
+ PasswordField passwordField = new PasswordField();
|
|
|
+ passwordField.setPromptText("必填");
|
|
|
+ TextField nicknameField = new TextField();
|
|
|
+ TextField emailField = new TextField();
|
|
|
+ TextField phoneField = new TextField();
|
|
|
+ TextField deptField = new TextField();
|
|
|
+ ComboBox<String> roleCombo = new ComboBox<>();
|
|
|
+ roleCombo.getItems().addAll("学生", "管理员");
|
|
|
+ ComboBox<String> sellerCombo = new ComboBox<>();
|
|
|
+ sellerCombo.getItems().addAll("否", "是");
|
|
|
+
|
|
|
+ if (!isNew) {
|
|
|
+ usernameField.setText(user.getUsername());
|
|
|
+ passwordField.setText(user.getPassword());
|
|
|
+ nicknameField.setText(user.getNickname());
|
|
|
+ emailField.setText(user.getEmail());
|
|
|
+ phoneField.setText(user.getPhone());
|
|
|
+ deptField.setText(user.getDept());
|
|
|
+ roleCombo.getSelectionModel().select(user.getRole() != null ? user.getRole() : 0);
|
|
|
+ sellerCombo.getSelectionModel().select(user.getIsSeller() != null && user.getIsSeller() == 1 ? 1 : 0);
|
|
|
+ } else {
|
|
|
+ sellerCombo.getSelectionModel().select(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ grid.add(new Label("用户名:"), 0, 0);
|
|
|
+ grid.add(usernameField, 1, 0);
|
|
|
+ grid.add(new Label("邮箱:"), 2, 0);
|
|
|
+ grid.add(emailField, 3, 0);
|
|
|
+ grid.add(new Label("密码:"), 0, 1);
|
|
|
+ grid.add(passwordField, 1, 1);
|
|
|
+ grid.add(new Label("电话:"), 2, 1);
|
|
|
+ grid.add(phoneField, 3, 1);
|
|
|
+ grid.add(new Label("昵称:"), 0, 2);
|
|
|
+ grid.add(nicknameField, 1, 2);
|
|
|
+ grid.add(new Label("院系:"), 2, 2);
|
|
|
+ grid.add(deptField, 3, 2);
|
|
|
+ grid.add(new Label("角色:"), 0, 3);
|
|
|
+ grid.add(roleCombo, 1, 3);
|
|
|
+ grid.add(new Label("卖家:"), 2, 3);
|
|
|
+ grid.add(sellerCombo, 3, 3);
|
|
|
+
|
|
|
+ dialog.getDialogPane().setContent(grid);
|
|
|
+
|
|
|
+ Node okBtn = dialog.getDialogPane().lookupButton(ButtonType.OK);
|
|
|
+ if (isNew) {
|
|
|
+ okBtn.setDisable(true);
|
|
|
+ usernameField.textProperty().addListener((obs, old, val) ->
|
|
|
+ okBtn.setDisable(val.trim().isEmpty() || passwordField.getText().trim().isEmpty()));
|
|
|
+ passwordField.textProperty().addListener((obs, old, val) ->
|
|
|
+ okBtn.setDisable(val.trim().isEmpty() || usernameField.getText().trim().isEmpty()));
|
|
|
+ }
|
|
|
+
|
|
|
+ dialog.setResultConverter(btn -> {
|
|
|
+ if (btn == ButtonType.OK) {
|
|
|
+ User u = isNew ? new User() : user;
|
|
|
+ u.setUsername(usernameField.getText().trim());
|
|
|
+ u.setPassword(passwordField.getText().trim());
|
|
|
+ u.setNickname(nicknameField.getText().trim());
|
|
|
+ u.setEmail(emailField.getText().trim());
|
|
|
+ u.setPhone(phoneField.getText().trim());
|
|
|
+ u.setDept(deptField.getText().trim());
|
|
|
+ u.setRole(roleCombo.getSelectionModel().getSelectedIndex());
|
|
|
+ u.setIsSeller(sellerCombo.getSelectionModel().getSelectedIndex());
|
|
|
+ return u;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ });
|
|
|
+
|
|
|
+ dialog.showAndWait().ifPresent(u -> {
|
|
|
+ if (isNew) {
|
|
|
+ RegisterRequest req = new RegisterRequest();
|
|
|
+ req.setUsername(u.getUsername());
|
|
|
+ req.setPassword(u.getPassword());
|
|
|
+ req.setNickname(u.getNickname());
|
|
|
+ req.setEmail(u.getEmail());
|
|
|
+ req.setPhone(u.getPhone());
|
|
|
+ req.setDept(u.getDept());
|
|
|
+ req.setRole(u.getRole());
|
|
|
+ req.setIsSeller(u.getIsSeller());
|
|
|
+ R<User> r = userService.register(req);
|
|
|
+ if (r.getCode() == 200) {
|
|
|
+ showInfo("用户已添加");
|
|
|
+ handleLoadAllUsers();
|
|
|
+ } else {
|
|
|
+ showAlert(r.getMessage());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ R<User> r = userService.update(u.getUserid(), u);
|
|
|
+ if (r.getCode() == 200) {
|
|
|
+ showInfo("用户信息已更新");
|
|
|
+ handleLoadAllUsers();
|
|
|
+ } else {
|
|
|
+ showAlert(r.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
private void showAlert(String message) {
|