初始版本,目前线上可用
1
backEnd/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
node_modules
|
||||||
0
backEnd/README.md
Normal file
24
backEnd/index.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
require("module-alias/register"); // 别名加载
|
||||||
|
|
||||||
|
import express from "express";
|
||||||
|
import bodyParser from "body-parser";
|
||||||
|
import routerIndex from "./src/router/index";
|
||||||
|
import { createConnection } from "typeorm";
|
||||||
|
import cors from "cors";
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const port = 8101;
|
||||||
|
createConnection().then(() => {
|
||||||
|
console.log("数据库连接成功!");
|
||||||
|
app.listen(port, () => {
|
||||||
|
console.log(`开始监听${port}了`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use(bodyParser.urlencoded({ extended: true })); // 进行url解码
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
|
||||||
|
app.use(cors());
|
||||||
|
|
||||||
|
// 匹配接口路由
|
||||||
|
app.use("/", routerIndex);
|
||||||
17
backEnd/ormconfig.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
const env = process.env.NODE_ENV;
|
||||||
|
module.exports = {
|
||||||
|
"type": "mysql",
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 3306,
|
||||||
|
"username": "root",
|
||||||
|
"password": "123456",
|
||||||
|
"database": "binyi",
|
||||||
|
"entities": ["./src/entity/*.ts"],
|
||||||
|
"migrations": ["src/migration/*.ts"],
|
||||||
|
"synchronize": true,
|
||||||
|
"logging": false,
|
||||||
|
"cli": {
|
||||||
|
"entitiesDir": "src/entity",
|
||||||
|
"migrationsDir": "src/migration"
|
||||||
|
}
|
||||||
|
}
|
||||||
7472
backEnd/package-lock.json
generated
Normal file
49
backEnd/package.json
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"name": "interface",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"type": "commonjs",
|
||||||
|
"main": "index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"db": "rd ./src/entity & typeorm-model-generator -h localhost -d baseSystem -p 3306 -u root -x 123456 -e mysql -o ./src/entity --noConfig true --ce pascal --cp camel",
|
||||||
|
"dev": "nodemon --watch 'src/**/*.ts' --exec ts-node ./index.ts --development",
|
||||||
|
"build": "webpack "
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/body-parser": "^1.19.2",
|
||||||
|
"@types/jsonwebtoken": "^9.0.9",
|
||||||
|
"axios": "^1.3.4",
|
||||||
|
"bcrypt": "^5.1.0",
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
|
"body-parser": "^1.20.2",
|
||||||
|
"dayjs": "^1.11.10",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"module-alias": "^2.2.3",
|
||||||
|
"multer": "^1.4.5-lts.1",
|
||||||
|
"mysql": "^2.18.1",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"ts-loader": "^9.5.1",
|
||||||
|
"typeorm": "^0.2.9",
|
||||||
|
"webpack": "^5.95.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bcrypt": "^5.0.0",
|
||||||
|
"@types/cors": "^2.8.17",
|
||||||
|
"@types/express": "^4.17.17",
|
||||||
|
"@types/module-alias": "^2.0.4",
|
||||||
|
"@types/mysql": "^2.15.21",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"webpack-cli": "^5.1.4"
|
||||||
|
},
|
||||||
|
"_moduleAliases": {
|
||||||
|
"@": "./src",
|
||||||
|
"@router": "./src/router",
|
||||||
|
"@entity": "./src/entity"
|
||||||
|
}
|
||||||
|
}
|
||||||
34
backEnd/src/abstrClass/BaseEntity.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
export abstract class BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn({ type: "int", name: "id" })
|
||||||
|
id: number;
|
||||||
|
@Column({
|
||||||
|
type: "datetime",
|
||||||
|
comment: "创建时间",
|
||||||
|
default: () => "CURRENT_TIMESTAMP",
|
||||||
|
transformer: {
|
||||||
|
to(value: Date) {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
from(value) {
|
||||||
|
return dayjs(new Date(value)).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
createDate: Date;
|
||||||
|
@Column({
|
||||||
|
type: "datetime",
|
||||||
|
comment: "更新时间",
|
||||||
|
default: () => "CURRENT_TIMESTAMP",
|
||||||
|
transformer: {
|
||||||
|
to(value: Date) {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
from(value) {
|
||||||
|
return dayjs(new Date(value)).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
updateDate: Date;
|
||||||
|
}
|
||||||
79
backEnd/src/entity/CancelPayment.ts
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
import { Entity, Column } from "typeorm";
|
||||||
|
|
||||||
|
@Entity("cacnle_payment")
|
||||||
|
export class CancelPayment extends BaseEntity {
|
||||||
|
@Column({
|
||||||
|
type: "datetime",
|
||||||
|
name: "checkout_date",
|
||||||
|
comment: "结账日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP",
|
||||||
|
})
|
||||||
|
checkoutDate: Date;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 50, comment: "经办人" })
|
||||||
|
handler: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "datetime",
|
||||||
|
name: "settlement_date",
|
||||||
|
comment: "结算日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP",
|
||||||
|
})
|
||||||
|
settlementDate: Date;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
name: "cash_amount",
|
||||||
|
comment: "现金金额",
|
||||||
|
})
|
||||||
|
cashAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
comment: "银联支付金额",
|
||||||
|
scale: 2,
|
||||||
|
name: "union_pay_amount",
|
||||||
|
})
|
||||||
|
unionPayAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
comment: "刷卡金额",
|
||||||
|
scale: 2,
|
||||||
|
name: "card_amount",
|
||||||
|
})
|
||||||
|
cardAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
comment: "对公转账金额",
|
||||||
|
name: "public_transfer_amount",
|
||||||
|
})
|
||||||
|
publicTransferAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
comment: "车间支付",
|
||||||
|
name: "workshop_payment",
|
||||||
|
})
|
||||||
|
workshopPayment: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "int",
|
||||||
|
comment: "单子ID",
|
||||||
|
name: "retail_id",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
retailId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CancelPayment;
|
||||||
89
backEnd/src/entity/CancelRetail.ts
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import { Entity, Column, OneToOne, JoinColumn } from "typeorm";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
import DeceasedRetail from "./DeceasedRetail";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
@Entity("cancel_retail")
|
||||||
|
export class CancelRetail extends BaseEntity {
|
||||||
|
@Column("int", {
|
||||||
|
name: "deceasedRetail_id",
|
||||||
|
comment: "销售单ID",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
deceasedRetailId: number;
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
name: "checkoutRetail_id",
|
||||||
|
comment: "服务销售单ID",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
checkoutRetailId: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "cancel_person",
|
||||||
|
length: 100,
|
||||||
|
comment: "作废申请人",
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
cancelPerson: string;
|
||||||
|
|
||||||
|
@Column("datetime", {
|
||||||
|
name: "cancel_date",
|
||||||
|
comment: "作废日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP", // 默认值为当前时间
|
||||||
|
transformer: {
|
||||||
|
to(value: Date) {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
from(value) {
|
||||||
|
return dayjs(new Date(value)).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
cancelDate: Date;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "cancel_reason",
|
||||||
|
comment: "作废原因",
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
cancelReason: string;
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
name: "examine_state",
|
||||||
|
comment: "审核状态 (0: 未审核, 1: 已审核, 2: 拒绝)",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
examineState: number;
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
name: "cancel_type",
|
||||||
|
comment: "作废类型,0结账处理、1零售结算",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
cancelType: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "examine_pserson",
|
||||||
|
comment: "审核人",
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
examinePserson: string;
|
||||||
|
|
||||||
|
@Column("datetime", {
|
||||||
|
name: "examine_date",
|
||||||
|
comment: "审核时间",
|
||||||
|
nullable: true, // 允许为空
|
||||||
|
transformer: {
|
||||||
|
to(value: Date) {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
from(value) {
|
||||||
|
return dayjs(new Date(value)).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
examineDate: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CancelRetail;
|
||||||
78
backEnd/src/entity/CheckoutPayment.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
import { Entity, Column } from "typeorm";
|
||||||
|
|
||||||
|
@Entity("checkout_payment_records")
|
||||||
|
export class CheckoutPaymentRecords extends BaseEntity {
|
||||||
|
@Column({
|
||||||
|
type: "datetime",
|
||||||
|
name: "checkout_date",
|
||||||
|
comment: "结账日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP",
|
||||||
|
})
|
||||||
|
checkoutDate: Date;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 50, comment: "经办人" })
|
||||||
|
handler: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "datetime",
|
||||||
|
name: "settlement_date",
|
||||||
|
comment: "结算日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP",
|
||||||
|
})
|
||||||
|
settlementDate: Date;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
name: "cash_amount",
|
||||||
|
comment: "现金金额",
|
||||||
|
})
|
||||||
|
cashAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
comment: "银联支付金额",
|
||||||
|
scale: 2,
|
||||||
|
name: "union_pay_amount",
|
||||||
|
})
|
||||||
|
unionPayAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
comment: "刷卡金额",
|
||||||
|
scale: 2,
|
||||||
|
name: "card_amount",
|
||||||
|
})
|
||||||
|
cardAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
comment: "对公转账金额",
|
||||||
|
name: "public_transfer_amount",
|
||||||
|
})
|
||||||
|
publicTransferAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
comment: "车间支付",
|
||||||
|
name: "workshop_payment",
|
||||||
|
})
|
||||||
|
workshopPayment: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "int",
|
||||||
|
comment: "单子ID",
|
||||||
|
name: "checkout_retail_id",
|
||||||
|
})
|
||||||
|
checkoutRetailId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CheckoutPaymentRecords;
|
||||||
85
backEnd/src/entity/CheckoutRetail.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import { Entity, Column } from "typeorm";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
@Entity("checkout_retail")
|
||||||
|
export class CheckoutRetail extends BaseEntity {
|
||||||
|
@Column("int", {
|
||||||
|
name: "deceased_id",
|
||||||
|
comment: "逝者ID",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
deceasedId: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "buyer",
|
||||||
|
comment: "购买人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
buyer: string;
|
||||||
|
|
||||||
|
@Column("datetime", {
|
||||||
|
name: "purchase_date",
|
||||||
|
comment: "购买日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP", // 默认值为当前时间
|
||||||
|
transformer: {
|
||||||
|
to(value: Date) {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
from(value) {
|
||||||
|
return dayjs(new Date(value)).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
purchaseDate: Date;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "handler",
|
||||||
|
comment: "经办人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
handler: string;
|
||||||
|
|
||||||
|
@Column("decimal", {
|
||||||
|
name: "sales_amount",
|
||||||
|
comment: "销售金额",
|
||||||
|
precision: 10,
|
||||||
|
scale: 2,
|
||||||
|
default: 0.0,
|
||||||
|
})
|
||||||
|
salesAmount: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "guide",
|
||||||
|
comment: "引导员",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
guide: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "service_items",
|
||||||
|
comment: "服务项目列表",
|
||||||
|
})
|
||||||
|
serviceItems: string;
|
||||||
|
|
||||||
|
// 0未结账、1已结账
|
||||||
|
@Column("int", {
|
||||||
|
name: "retail_state",
|
||||||
|
comment: "结账状态",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
retailState: number;
|
||||||
|
|
||||||
|
// 0正常、1已作废
|
||||||
|
@Column("int", {
|
||||||
|
name: "cancel_state",
|
||||||
|
comment: "作废状态",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
cancelState: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CheckoutRetail;
|
||||||
117
backEnd/src/entity/Deceased.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { Entity, Column } from "typeorm";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
@Entity("deceased")
|
||||||
|
export class Deceased extends BaseEntity {
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "name",
|
||||||
|
comment: "逝者姓名",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "id_number",
|
||||||
|
comment: "证件号码",
|
||||||
|
length: 50,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
idNumber: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "gender",
|
||||||
|
comment: "性别",
|
||||||
|
length: 10,
|
||||||
|
default: "男",
|
||||||
|
})
|
||||||
|
gender: string;
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
comment: "年龄",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
age: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "buyer",
|
||||||
|
comment: "购买人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
buyer: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "family_name",
|
||||||
|
comment: "购买人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
familyName: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "family_phone",
|
||||||
|
comment: "购买人电话",
|
||||||
|
length: 255,
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
familyPhone: string;
|
||||||
|
|
||||||
|
@Column({ comment: "所在省", default: "" })
|
||||||
|
province: string; // 所在省
|
||||||
|
@Column({ comment: "所在市", default: "" })
|
||||||
|
city: string; // 所在市
|
||||||
|
@Column({ comment: "所在区域", default: "" })
|
||||||
|
area: string; // 所在区域
|
||||||
|
@Column({ comment: "详细地址", default: "" })
|
||||||
|
address: string; // 详细地址
|
||||||
|
|
||||||
|
@Column("datetime", {
|
||||||
|
name: "purchase_date",
|
||||||
|
comment: "购买日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP", // 默认值为当前时间
|
||||||
|
transformer: {
|
||||||
|
to(value: Date) {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
from(value) {
|
||||||
|
return dayjs(new Date(value)).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
purchaseDate: Date;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "handler",
|
||||||
|
comment: "经办人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
handler: string;
|
||||||
|
|
||||||
|
@Column("decimal", {
|
||||||
|
name: "sales_amount",
|
||||||
|
comment: "销售金额",
|
||||||
|
precision: 10,
|
||||||
|
scale: 2,
|
||||||
|
default: 0.0,
|
||||||
|
})
|
||||||
|
salesAmount: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "guide",
|
||||||
|
comment: "引导员",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
guide: string;
|
||||||
|
|
||||||
|
@Column("simple-array", {
|
||||||
|
name: "service_items",
|
||||||
|
comment: "服务项目列表",
|
||||||
|
})
|
||||||
|
serviceItems: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Deceased;
|
||||||
143
backEnd/src/entity/DeceasedRetail.ts
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
import { Entity, Column, Index } from "typeorm";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
@Entity("deceased_retail")
|
||||||
|
export class DeceasedRetail extends BaseEntity {
|
||||||
|
@Index()
|
||||||
|
@Column("int", {
|
||||||
|
name: "deceased_id",
|
||||||
|
comment: "逝者ID",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
deceasedId: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "deceased_name",
|
||||||
|
comment: "购买人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
deceasedName: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "buyer",
|
||||||
|
comment: "购买人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
buyer: string;
|
||||||
|
|
||||||
|
@Column("datetime", {
|
||||||
|
name: "purchase_date",
|
||||||
|
comment: "录单日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP", // 默认值为当前时间
|
||||||
|
transformer: {
|
||||||
|
to(value: Date) {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
from(value) {
|
||||||
|
return dayjs(new Date(value)).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
purchaseDate: Date;
|
||||||
|
|
||||||
|
@Column("datetime", {
|
||||||
|
name: "checkout_date",
|
||||||
|
comment: "录单日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP", // 默认值为当前时间
|
||||||
|
transformer: {
|
||||||
|
to(value: Date) {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
from(value) {
|
||||||
|
return dayjs(new Date(value)).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
checkoutDate: Date;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "handler",
|
||||||
|
comment: "经办人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
handler: string;
|
||||||
|
|
||||||
|
@Column("decimal", {
|
||||||
|
name: "sales_amount",
|
||||||
|
comment: "销售金额",
|
||||||
|
precision: 10,
|
||||||
|
scale: 2,
|
||||||
|
default: 0.0,
|
||||||
|
})
|
||||||
|
salesAmount: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "guide",
|
||||||
|
comment: "引导员",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
guide: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "service_items",
|
||||||
|
comment: "服务项目列表",
|
||||||
|
})
|
||||||
|
serviceItems: string;
|
||||||
|
|
||||||
|
// 0未结账、1已结账
|
||||||
|
@Column("int", {
|
||||||
|
name: "retail_state",
|
||||||
|
comment: "结账状态",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
retailState: number;
|
||||||
|
|
||||||
|
// 0正常、1已作废
|
||||||
|
@Column("int", {
|
||||||
|
name: "cancel_state",
|
||||||
|
comment: "作废状态",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
cancelState: number;
|
||||||
|
|
||||||
|
// 0服务单、1有逝者零售单, 2 无逝者零售单
|
||||||
|
@Column("int", {
|
||||||
|
name: "retail_type",
|
||||||
|
comment: "单子类型",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
retailType: number;
|
||||||
|
|
||||||
|
//无逝者零售单
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "family_name",
|
||||||
|
comment: "购买人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
familyName: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "family_phone",
|
||||||
|
comment: "购买人电话",
|
||||||
|
length: 255,
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
familyPhone: string;
|
||||||
|
|
||||||
|
@Column({ comment: "所在省", default: "" })
|
||||||
|
province: string; // 所在省
|
||||||
|
@Column({ comment: "所在市", default: "" })
|
||||||
|
city: string; // 所在市
|
||||||
|
@Column({ comment: "所在区域", default: "" })
|
||||||
|
area: string; // 所在区域
|
||||||
|
@Column({ comment: "详细地址", default: "" })
|
||||||
|
address: string; // 详细地址
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DeceasedRetail;
|
||||||
102
backEnd/src/entity/Payment.ts
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
OneToOne,
|
||||||
|
JoinColumn,
|
||||||
|
} from "typeorm";
|
||||||
|
import DeceasedRetail from "./DeceasedRetail";
|
||||||
|
|
||||||
|
@Entity("payment_records")
|
||||||
|
export class PaymentRecord extends BaseEntity {
|
||||||
|
@Column({
|
||||||
|
type: "datetime",
|
||||||
|
name: "checkout_date",
|
||||||
|
comment: "结账日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP",
|
||||||
|
})
|
||||||
|
checkoutDate: Date;
|
||||||
|
|
||||||
|
@Column({ type: "varchar", length: 50, comment: "经办人" })
|
||||||
|
handler: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "datetime",
|
||||||
|
name: "settlement_date",
|
||||||
|
comment: "结算日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP",
|
||||||
|
})
|
||||||
|
settlementDate: Date;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
name: "cash_amount",
|
||||||
|
comment: "现金金额",
|
||||||
|
})
|
||||||
|
cashAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
comment: "银联支付金额",
|
||||||
|
scale: 2,
|
||||||
|
name: "union_pay_amount",
|
||||||
|
})
|
||||||
|
unionPayAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
comment: "刷卡金额",
|
||||||
|
scale: 2,
|
||||||
|
name: "card_amount",
|
||||||
|
})
|
||||||
|
cardAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
comment: "对公转账金额",
|
||||||
|
name: "public_transfer_amount",
|
||||||
|
})
|
||||||
|
publicTransferAmount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "decimal",
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
comment: "车间支付",
|
||||||
|
name: "workshop_payment",
|
||||||
|
})
|
||||||
|
workshopPayment: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "int",
|
||||||
|
comment: "零售单子ID",
|
||||||
|
default: 0,
|
||||||
|
name: "deceased_retail_id",
|
||||||
|
})
|
||||||
|
deceasedRetailId: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "int",
|
||||||
|
comment: "无零售单子ID",
|
||||||
|
name: "no_deceased_retail_id",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
noDeceasedRetailId: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: "int",
|
||||||
|
comment: "单子ID",
|
||||||
|
name: "retail_id",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
retailId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PaymentRecord;
|
||||||
12
backEnd/src/entity/Role.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { Column, Entity } from "typeorm";
|
||||||
|
import { BaseEntity } from "../abstrClass/BaseEntity";
|
||||||
|
|
||||||
|
@Entity("role")
|
||||||
|
export class Role extends BaseEntity {
|
||||||
|
@Column({ type: "varchar", comment: "角色值", default: "" })
|
||||||
|
values: string;
|
||||||
|
@Column({ type: "int", comment: "角色状态", default: 1 })
|
||||||
|
roleState: number;
|
||||||
|
@Column({ type: "varchar", comment: "角色名", default: "" })
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
53
backEnd/src/entity/SeletedServiceList.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { Entity, Column } from "typeorm";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
|
||||||
|
@Entity("seleted_service_list")
|
||||||
|
export class SeletedServiceList extends BaseEntity {
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "name",
|
||||||
|
comment: "服务项目名称",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
comment: "数量",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
quantity: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "unit",
|
||||||
|
comment: "单位",
|
||||||
|
length: 50,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
unit: string;
|
||||||
|
|
||||||
|
@Column("decimal", {
|
||||||
|
name: "price",
|
||||||
|
comment: "售价",
|
||||||
|
precision: 10,
|
||||||
|
scale: 2,
|
||||||
|
default: 0.0,
|
||||||
|
})
|
||||||
|
price: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "remark",
|
||||||
|
comment: "备注",
|
||||||
|
length: 500,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
remark: string;
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
name: "retail_id",
|
||||||
|
comment: "所属零售ID",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
retailId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SeletedServiceList;
|
||||||
30
backEnd/src/entity/ServiceCategory.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { Entity, Column } from "typeorm";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
|
||||||
|
@Entity("service_category")
|
||||||
|
export class ServiceCategory extends BaseEntity {
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "name",
|
||||||
|
comment: "商品分类名称",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
name: string; // 商品分类名称
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "remark",
|
||||||
|
comment: "备注",
|
||||||
|
length: 500,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
remark: string;
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
name: "parentId",
|
||||||
|
comment: "分类ID",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
parentId: number; // 关联分类
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServiceCategory;
|
||||||
60
backEnd/src/entity/ServiceItem.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { Entity, Column } from "typeorm";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
|
||||||
|
@Entity("service_item")
|
||||||
|
export class ServiceItem extends BaseEntity {
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "name",
|
||||||
|
comment: "服务项目名称",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
comment: "数量",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
quantity: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "unit",
|
||||||
|
comment: "单位",
|
||||||
|
length: 50,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
unit: string;
|
||||||
|
|
||||||
|
@Column("decimal", {
|
||||||
|
name: "price",
|
||||||
|
comment: "售价",
|
||||||
|
precision: 10,
|
||||||
|
scale: 2,
|
||||||
|
default: 0.0,
|
||||||
|
})
|
||||||
|
price: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "remark",
|
||||||
|
comment: "备注",
|
||||||
|
length: 500,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
remark: string;
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
name: "parentId",
|
||||||
|
comment: "分类ID",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
parentId: number; // 关联分类
|
||||||
|
|
||||||
|
@Column("int", {
|
||||||
|
name: "hasDeceased",
|
||||||
|
comment: "是否有逝者",
|
||||||
|
default: 1,
|
||||||
|
})
|
||||||
|
hasDeceased: number; // 关联分类
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServiceItem;
|
||||||
28
backEnd/src/entity/SystemMenue.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
|
||||||
|
@Entity("system_menue")
|
||||||
|
export class SystemMenue {
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column({ comment: "菜单名", default: "" })
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column({ comment: "创建时间", default: "" })
|
||||||
|
createDate: string;
|
||||||
|
|
||||||
|
@Column({ comment: "更新时间", default: "" })
|
||||||
|
updateDate: string;
|
||||||
|
|
||||||
|
@Column({ comment: "路径名", default: "" })
|
||||||
|
path: string;
|
||||||
|
|
||||||
|
@Column({ comment: "父级ID", default: 0 })
|
||||||
|
parentId: number;
|
||||||
|
|
||||||
|
@Column({ comment: "图标", default: "" })
|
||||||
|
icon: string;
|
||||||
|
|
||||||
|
@Column({ comment: "是否显示", default: true })
|
||||||
|
show: boolean;
|
||||||
|
}
|
||||||
45
backEnd/src/entity/User.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
|
||||||
|
@Entity("user")
|
||||||
|
export class User extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn({ type: "int", name: "id" })
|
||||||
|
id: number;
|
||||||
|
@Column("varchar", { name: "name", comment: "姓名\r\n", length: 255 })
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "phone",
|
||||||
|
nullable: true,
|
||||||
|
comment: "电话",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
phone: string;
|
||||||
|
@Column({ comment: "性别", default: "男" })
|
||||||
|
sex: string;
|
||||||
|
@Column("varchar", { name: "pwd", nullable: true, length: 255 })
|
||||||
|
pwd: string;
|
||||||
|
@Column({
|
||||||
|
comment: "创建时间",
|
||||||
|
default: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
})
|
||||||
|
@Column({ comment: "用户状态", default: 1 })
|
||||||
|
userState: number; // 账户状态
|
||||||
|
@Column({ comment: "角色", default: "" })
|
||||||
|
role: string; // 角色
|
||||||
|
@Column({ comment: "生日", default: "" })
|
||||||
|
birthday: string; // 生日
|
||||||
|
@Column({ comment: "年龄", default: "" })
|
||||||
|
age: string; // 年龄
|
||||||
|
@Column({ comment: "所在省", default: "" })
|
||||||
|
province: string; // 所在省
|
||||||
|
@Column({ comment: "所在市", default: "" })
|
||||||
|
city: string; // 所在市
|
||||||
|
@Column({ comment: "所在区域", default: "" })
|
||||||
|
area: string; // 所在区域
|
||||||
|
@Column({ comment: "详细地址", default: "" })
|
||||||
|
address: string; // 详细地址
|
||||||
|
}
|
||||||
|
export default User;
|
||||||
94
backEnd/src/entity/noDeceasedRetail.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import { Entity, Column } from "typeorm";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
@Entity("nodeceased_retail")
|
||||||
|
export class noDeceasedRetail extends BaseEntity {
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "buyer",
|
||||||
|
comment: "购买人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
buyer: string;
|
||||||
|
|
||||||
|
@Column("datetime", {
|
||||||
|
name: "purchase_date",
|
||||||
|
comment: "购买日期",
|
||||||
|
default: () => "CURRENT_TIMESTAMP", // 默认值为当前时间
|
||||||
|
transformer: {
|
||||||
|
to(value: Date) {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
from(value) {
|
||||||
|
return dayjs(new Date(value)).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
purchaseDate: Date;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "handler",
|
||||||
|
comment: "经办人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
handler: string;
|
||||||
|
|
||||||
|
@Column("decimal", {
|
||||||
|
name: "sales_amount",
|
||||||
|
comment: "销售金额",
|
||||||
|
precision: 10,
|
||||||
|
scale: 2,
|
||||||
|
default: 0.0,
|
||||||
|
})
|
||||||
|
salesAmount: number;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "guide",
|
||||||
|
comment: "引导员",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
guide: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "family_name",
|
||||||
|
comment: "购买人",
|
||||||
|
length: 255,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
familyName: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "family_phone",
|
||||||
|
comment: "购买人电话",
|
||||||
|
length: 255,
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
familyPhone: string;
|
||||||
|
|
||||||
|
@Column("varchar", {
|
||||||
|
name: "service_items",
|
||||||
|
comment: "服务项目列表",
|
||||||
|
})
|
||||||
|
serviceItems: string;
|
||||||
|
|
||||||
|
// 0未结账、1已结账
|
||||||
|
@Column("int", {
|
||||||
|
name: "retail_state",
|
||||||
|
comment: "结账状态",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
retailState: number;
|
||||||
|
|
||||||
|
// 0正常、1已作废
|
||||||
|
@Column("int", {
|
||||||
|
name: "cancel_state",
|
||||||
|
comment: "作废状态",
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
cancelState: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default noDeceasedRetail;
|
||||||
101
backEnd/src/lib/curd/curd.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import { Request } from "express";
|
||||||
|
import { Repository, getConnection } from "typeorm";
|
||||||
|
import { filterObjEmptyVal } from "@/util/globalMethods";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import pagination from "../pagination/pagination";
|
||||||
|
import { BaseEntity } from "@/abstrClass/BaseEntity";
|
||||||
|
import getBuilderPagination from "../pagination/builderPagination";
|
||||||
|
|
||||||
|
interface CurdOptions<T> {
|
||||||
|
entity: { new (): T } & typeof BaseEntity; // 确保实体继承 BaseEntity
|
||||||
|
req: Request;
|
||||||
|
params?: Partial<T>;
|
||||||
|
}
|
||||||
|
class Curd<T extends BaseEntity> {
|
||||||
|
private entity: { new (): T };
|
||||||
|
private req: Request;
|
||||||
|
private queryParams?: { [key: string]: any };
|
||||||
|
private repositrory: Repository<unknown>;
|
||||||
|
private params?: Partial<T>;
|
||||||
|
|
||||||
|
constructor(options: CurdOptions<T> & { repository?: Repository<T> }) {
|
||||||
|
if (!options.entity) throw Error("请传入实体类");
|
||||||
|
if (!options.req)
|
||||||
|
throw Error("请传express的Request参数,一般在中间件回调中的第一个参数");
|
||||||
|
// if (!options.params) throw Error("请传入需要操作的条件对象,用于sql查询");
|
||||||
|
this.req = options.req;
|
||||||
|
this.entity = options.entity;
|
||||||
|
|
||||||
|
this.repositrory =
|
||||||
|
options.repository || getConnection().getRepository(options.entity);
|
||||||
|
this.queryParams =
|
||||||
|
this.req.method === "GET" ? this.req.query : this.req.body;
|
||||||
|
|
||||||
|
this.params = options.params;
|
||||||
|
}
|
||||||
|
|
||||||
|
async add() {
|
||||||
|
let addData = { ...new this.entity(), ...this.queryParams };
|
||||||
|
|
||||||
|
addData.updateDate = new Date();
|
||||||
|
addData.createDate = new Date();
|
||||||
|
|
||||||
|
return await this.repositrory.save(addData);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete() {
|
||||||
|
if (!this.queryParams?.id)
|
||||||
|
return {
|
||||||
|
code: 500,
|
||||||
|
msg: "没有传入需要删除数据的ID",
|
||||||
|
};
|
||||||
|
let queryData = await this.repositrory.findOne({
|
||||||
|
where: { id: this.queryParams.id },
|
||||||
|
});
|
||||||
|
if (!queryData) return { code: 500, msg: "删除的数据不存在" };
|
||||||
|
await this.repositrory.remove(queryData);
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
msg: "删除成功",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async update() {
|
||||||
|
let body = this.queryParams;
|
||||||
|
await this.repositrory.update(
|
||||||
|
{ id: body.id },
|
||||||
|
{ ...this.queryParams, updateDate: new Date() }
|
||||||
|
);
|
||||||
|
|
||||||
|
return await this.repositrory.findOne(this.queryParams.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async query() {
|
||||||
|
return await this.repositrory.find({
|
||||||
|
where: filterObjEmptyVal({ ...this.queryParams, ...this.params }),
|
||||||
|
order: {
|
||||||
|
createDate: "DESC",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async queryList() {
|
||||||
|
return await pagination(
|
||||||
|
this.entity,
|
||||||
|
this.req,
|
||||||
|
filterObjEmptyVal({ ...this.queryParams, ...this.params })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
async queryBuilderList() {
|
||||||
|
return await getBuilderPagination(
|
||||||
|
this.entity,
|
||||||
|
this.req,
|
||||||
|
filterObjEmptyVal({ ...this.queryParams, ...this.params })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function curd<T extends BaseEntity>(
|
||||||
|
options: CurdOptions<T>
|
||||||
|
): Curd<T> {
|
||||||
|
return new Curd(options);
|
||||||
|
}
|
||||||
32
backEnd/src/lib/menueToTree.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { SystemMenue } from "../entity/SystemMenue";
|
||||||
|
interface routerTree extends SystemMenue {
|
||||||
|
children?: SystemMenue[];
|
||||||
|
}
|
||||||
|
let filterKey = (obj: SystemMenue) => {
|
||||||
|
delete obj.id;
|
||||||
|
delete obj.updateDate;
|
||||||
|
delete obj.createDate;
|
||||||
|
delete obj.parentId;
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
export default function menueToTree(data: SystemMenue[]): routerTree[] {
|
||||||
|
let dataList = [];
|
||||||
|
if (!data.some((item) => item.parentId === 0)) {
|
||||||
|
return data.map((item) => filterKey(item));
|
||||||
|
}
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
let item: routerTree = data[i];
|
||||||
|
|
||||||
|
item.children = [];
|
||||||
|
|
||||||
|
for (let j = 0; j < data.length; j++) {
|
||||||
|
let childrenItem = data[j];
|
||||||
|
if (childrenItem.parentId === item.id) {
|
||||||
|
item.children.push(filterKey({ ...childrenItem }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 只添加父级
|
||||||
|
if (!item.parentId) dataList.push(filterKey({ ...item }));
|
||||||
|
}
|
||||||
|
return dataList;
|
||||||
|
}
|
||||||
113
backEnd/src/lib/pagination/builderPagination.ts
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import { getConnection, Between, Brackets } from "typeorm";
|
||||||
|
import { Request } from "express";
|
||||||
|
|
||||||
|
type paginationType<T> = {
|
||||||
|
list: T[];
|
||||||
|
total: number;
|
||||||
|
pageSize: number;
|
||||||
|
pageNumber: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterKeys = ["pwd"];
|
||||||
|
const DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
||||||
|
|
||||||
|
export default async function getBuilderPagination<T>(
|
||||||
|
entity: Function,
|
||||||
|
req: Request,
|
||||||
|
queryParams?: { [key: string]: any }
|
||||||
|
): Promise<paginationType<T>> {
|
||||||
|
try {
|
||||||
|
// 获取分页参数
|
||||||
|
const { pageSize, pageNumber } = getPaginationParams(req);
|
||||||
|
const repository = getConnection().manager.getRepository(entity);
|
||||||
|
const alias = "entity";
|
||||||
|
|
||||||
|
// 创建 QueryBuilder
|
||||||
|
const queryBuilder = repository.createQueryBuilder(alias);
|
||||||
|
// 处理查询参数
|
||||||
|
if (queryParams) {
|
||||||
|
Object.entries(queryParams).forEach(([key, value]) => {
|
||||||
|
if (!["pageSize", "pageNumber"].includes(key)) {
|
||||||
|
// 新增非空条件处理
|
||||||
|
if (value === "NOT_EMPTY") {
|
||||||
|
queryBuilder.andWhere(
|
||||||
|
new Brackets((qb) => {
|
||||||
|
qb.where(`${alias}.${key} IS NOT NULL`).andWhere(
|
||||||
|
`${alias}.${key} != ''`
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 处理日期范围
|
||||||
|
else if (typeof value === "string" && DATE_REGEX.test(value)) {
|
||||||
|
const start = new Date(`${value}T00:00:00`);
|
||||||
|
const end = new Date(`${value}T23:59:59`);
|
||||||
|
queryBuilder.andWhere(
|
||||||
|
new Brackets((qb) =>
|
||||||
|
qb
|
||||||
|
.where(`${alias}.${key} >= :start`, { start })
|
||||||
|
.andWhere(`${alias}.${key} <= :end`, { end })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 处理普通参数
|
||||||
|
else if (value !== undefined) {
|
||||||
|
// 处理数组参数(如?status=1,2,3)
|
||||||
|
if (typeof value === "string" && value.includes(",")) {
|
||||||
|
queryBuilder.andWhere(`${alias}.${key} IN (:...${key})`, {
|
||||||
|
[key]: value.split(","),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 处理普通值
|
||||||
|
else {
|
||||||
|
queryBuilder.andWhere(`${alias}.${key} = :${key}`, {
|
||||||
|
[key]: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加排序
|
||||||
|
queryBuilder.orderBy(`${alias}.createDate`, "DESC");
|
||||||
|
|
||||||
|
// 执行分页查询
|
||||||
|
const [list, total] = await queryBuilder
|
||||||
|
.skip((pageNumber - 1) * pageSize)
|
||||||
|
.take(pageSize)
|
||||||
|
.getManyAndCount();
|
||||||
|
|
||||||
|
// 过滤敏感字段
|
||||||
|
const filteredList = list.map((item: any) => {
|
||||||
|
const filtered = { ...item };
|
||||||
|
filterKeys.forEach((key) => delete filtered[key]);
|
||||||
|
return filtered;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
list: filteredList,
|
||||||
|
total,
|
||||||
|
pageSize,
|
||||||
|
pageNumber,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`分页查询出错: ${err.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分页参数
|
||||||
|
*/
|
||||||
|
function getPaginationParams(req: Request): {
|
||||||
|
pageSize: number;
|
||||||
|
pageNumber: number;
|
||||||
|
} {
|
||||||
|
const { pageSize = 10, pageNumber = 1 } =
|
||||||
|
req.method === "GET" ? req.query : req.body;
|
||||||
|
|
||||||
|
return {
|
||||||
|
pageSize: Math.max(1, parseInt(pageSize as string, 10)),
|
||||||
|
pageNumber: Math.max(1, parseInt(pageNumber as string, 10)),
|
||||||
|
};
|
||||||
|
}
|
||||||
97
backEnd/src/lib/pagination/multPagination.ts
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import { Request } from "express";
|
||||||
|
|
||||||
|
type paginationType<T> = {
|
||||||
|
list: T[] | any[];
|
||||||
|
total: number;
|
||||||
|
pageSize: number;
|
||||||
|
pageNumber: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterKeys = ["pwd"];
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param entites 传入实体类数组以供查询(支持多表)
|
||||||
|
* @param req express的Request请求体
|
||||||
|
* @param queryParams 查询参数
|
||||||
|
* @param aliasMap 表别名映射,键为实体类名,值为别名
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default async function MultPagination<T>(
|
||||||
|
entites: Function[],
|
||||||
|
req: Request,
|
||||||
|
queryParams?: { [key: string]: any },
|
||||||
|
aliasMap: { [key: string]: string } = {}
|
||||||
|
): Promise<paginationType<T>> {
|
||||||
|
const { pageSize, pageNumber } = getPaginationParams(req);
|
||||||
|
|
||||||
|
// 获取 QueryBuilder
|
||||||
|
const queryBuilder = getConnection().createQueryBuilder();
|
||||||
|
|
||||||
|
// 构造 FROM 部分,支持多表
|
||||||
|
entites.forEach((entite, index) => {
|
||||||
|
const alias = aliasMap[entite.name] || `alias${index}`;
|
||||||
|
if (index === 0) {
|
||||||
|
queryBuilder.from(entite, alias); // 主表
|
||||||
|
} else {
|
||||||
|
queryBuilder.leftJoinAndSelect(entite, alias); // 关联表
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 构造 WHERE 条件
|
||||||
|
if (queryParams) {
|
||||||
|
Object.entries(queryParams).forEach(([key, value]) => {
|
||||||
|
queryBuilder.andWhere(`${getWhereKey(key, aliasMap)} = :${key}`, {
|
||||||
|
[key]: value,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造排序
|
||||||
|
queryBuilder.orderBy("alias0.createDate", "ASC");
|
||||||
|
|
||||||
|
// 分页处理
|
||||||
|
queryBuilder.skip((pageNumber - 1) * pageSize).take(pageSize);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [list, total] = await queryBuilder.getManyAndCount();
|
||||||
|
|
||||||
|
// 过滤敏感数据
|
||||||
|
list.forEach((item) => {
|
||||||
|
filterKeys.forEach((key) => {
|
||||||
|
delete item[key];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
list,
|
||||||
|
total,
|
||||||
|
pageSize,
|
||||||
|
pageNumber,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error("分页查询出错:" + err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPaginationParams(req: Request): {
|
||||||
|
pageSize: number;
|
||||||
|
pageNumber: number;
|
||||||
|
} {
|
||||||
|
const { pageSize = 10, pageNumber = 1 } =
|
||||||
|
req.method === "GET" ? req.query : req.body;
|
||||||
|
const realPageSize = Math.max(1, parseInt(pageSize as string, 10));
|
||||||
|
const realPageNumber = Math.max(1, parseInt(pageNumber as string, 10));
|
||||||
|
return { pageSize: realPageSize, pageNumber: realPageNumber };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取WHERE条件时自动识别别名
|
||||||
|
function getWhereKey(key: string, aliasMap: { [key: string]: string }) {
|
||||||
|
for (const alias in aliasMap) {
|
||||||
|
if (key.startsWith(alias + ".")) {
|
||||||
|
return key; // 已包含别名
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `alias0.${key}`; // 默认主表
|
||||||
|
}
|
||||||
83
backEnd/src/lib/pagination/pagination.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import { getConnection, Between } from "typeorm";
|
||||||
|
import { Request } from "express";
|
||||||
|
|
||||||
|
type paginationType<T> = {
|
||||||
|
list: T[] | any[];
|
||||||
|
total: number;
|
||||||
|
pageSize: number;
|
||||||
|
pageNumber: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterKeys = ["pwd"];
|
||||||
|
const DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理日期查询参数
|
||||||
|
*/
|
||||||
|
function processDateParams(params: { [key: string]: any }): {
|
||||||
|
[key: string]: any;
|
||||||
|
} {
|
||||||
|
const processed = {} as Record<string, any>;
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(params)) {
|
||||||
|
if (typeof value === "string" && DATE_REGEX.test(value)) {
|
||||||
|
// 处理日期范围
|
||||||
|
const start = new Date(`${value}T00:00:00`);
|
||||||
|
const end = new Date(`${value}T23:59:59`);
|
||||||
|
processed[key] = Between(start, end);
|
||||||
|
} else {
|
||||||
|
processed[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return processed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分页参数
|
||||||
|
*/
|
||||||
|
function getPaginationParams(req: Request): {
|
||||||
|
pageSize: number;
|
||||||
|
pageNumber: number;
|
||||||
|
} {
|
||||||
|
const { pageSize = 10, pageNumber = 1 } =
|
||||||
|
req.method === "GET" ? req.query : req.body;
|
||||||
|
|
||||||
|
return {
|
||||||
|
pageSize: Math.max(1, parseInt(pageSize as string, 10)),
|
||||||
|
pageNumber: Math.max(1, parseInt(pageNumber as string, 10)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询封装
|
||||||
|
*/
|
||||||
|
export default async function getPagination<T>(
|
||||||
|
entity: Function,
|
||||||
|
req: Request,
|
||||||
|
queryParams?: { [key: string]: any }
|
||||||
|
): Promise<paginationType<T>> {
|
||||||
|
try {
|
||||||
|
const { pageSize, pageNumber } = getPaginationParams(req);
|
||||||
|
const repository = getConnection().manager.getRepository(entity);
|
||||||
|
|
||||||
|
// 处理日期查询参数
|
||||||
|
const processedWhere = queryParams ? processDateParams(queryParams) : {};
|
||||||
|
|
||||||
|
const [list, total] = await repository.findAndCount({
|
||||||
|
where: processedWhere,
|
||||||
|
order: { createDate: "DESC" },
|
||||||
|
skip: (pageNumber - 1) * pageSize,
|
||||||
|
take: pageSize,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 过滤敏感字段
|
||||||
|
list.forEach((item) => {
|
||||||
|
filterKeys.forEach((key) => delete item[key]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return { list, total, pageSize, pageNumber };
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`分页查询出错: ${err.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
220
backEnd/src/router/CheckoutRetail/CheckoutRetail.ts
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { Brackets, getConnection } from "typeorm";
|
||||||
|
|
||||||
|
import Deceased from "@/entity/Deceased";
|
||||||
|
import CheckoutPayment from "@/entity/CheckoutPayment";
|
||||||
|
import DeceasedRetail from "@/entity/DeceasedRetail";
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
|
||||||
|
import parseRangDate, {
|
||||||
|
filterObjEmptyVal,
|
||||||
|
getPaginationParams,
|
||||||
|
} from "@/util/globalMethods";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// 统一查询方法
|
||||||
|
async function queryRetailRecords(params: {
|
||||||
|
req: Request;
|
||||||
|
retailState?: number;
|
||||||
|
isQuery?: boolean;
|
||||||
|
}): Promise<{
|
||||||
|
list: any[];
|
||||||
|
total: number;
|
||||||
|
pageSize: number;
|
||||||
|
pageNumber: number;
|
||||||
|
}> {
|
||||||
|
const { req, retailState } = params;
|
||||||
|
const { pageSize, pageNumber } = getPaginationParams(req);
|
||||||
|
const alias = "r";
|
||||||
|
const paymentAlias = "p";
|
||||||
|
const deceasedAlias = "d";
|
||||||
|
|
||||||
|
let { startDate, endDate } = parseRangDate(req);
|
||||||
|
// 初始化查询构造器
|
||||||
|
const queryBuilder = getConnection()
|
||||||
|
.getRepository(DeceasedRetail)
|
||||||
|
.createQueryBuilder(alias)
|
||||||
|
.leftJoinAndMapOne(
|
||||||
|
`${alias}.paymentRecord`,
|
||||||
|
CheckoutPayment,
|
||||||
|
paymentAlias,
|
||||||
|
`${paymentAlias}.checkout_retail_id = ${alias}.id`
|
||||||
|
)
|
||||||
|
.leftJoinAndMapOne(
|
||||||
|
`${alias}.deceased`,
|
||||||
|
Deceased,
|
||||||
|
deceasedAlias,
|
||||||
|
`${deceasedAlias}.id = ${alias}.deceasedId`
|
||||||
|
)
|
||||||
|
.where(`${alias}.retailType = 0`)
|
||||||
|
.andWhere(`${alias}.cancelState = 0`);
|
||||||
|
|
||||||
|
// 零售状态筛选
|
||||||
|
if (typeof retailState === "number") {
|
||||||
|
queryBuilder.andWhere(`${alias}.retailState = :retailState`, {
|
||||||
|
retailState,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
queryBuilder.andWhere(
|
||||||
|
new Brackets((qb) =>
|
||||||
|
qb
|
||||||
|
.where(`${alias}.serviceItems IS NOT NULL`)
|
||||||
|
.andWhere(`${alias}.serviceItems != ''`)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (startDate && endDate) {
|
||||||
|
queryBuilder
|
||||||
|
.andWhere(`p.checkoutDate BETWEEN :start AND :end`)
|
||||||
|
.setParameters({ start: startDate, end: endDate });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态处理查询参数
|
||||||
|
const queryParams: any = filterObjEmptyVal(
|
||||||
|
req.method === "GET" ? req.query : req.body
|
||||||
|
);
|
||||||
|
Object.entries(queryParams).forEach(([key, value]) => {
|
||||||
|
if (["pageSize", "pageNumber"].includes(key)) return;
|
||||||
|
if (value === undefined || value === "") return;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
// case "checkoutDate":
|
||||||
|
// queryBuilder.andWhere(`${paymentAlias}.checkoutDate = :checkoutDate`, {
|
||||||
|
// checkoutDate: value,
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
case "gender":
|
||||||
|
queryBuilder.andWhere(`${deceasedAlias}.gender = :gender`, {
|
||||||
|
gender: value,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "name":
|
||||||
|
queryBuilder.andWhere(`${deceasedAlias}.name LIKE :name`, {
|
||||||
|
name: `%${value}%`,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (key.startsWith("deceased.")) {
|
||||||
|
const field = key.split(".")[1];
|
||||||
|
queryBuilder.andWhere(`${deceasedAlias}.${field} = :${field}`, {
|
||||||
|
[field]: value,
|
||||||
|
});
|
||||||
|
} else if (
|
||||||
|
Object.keys(queryBuilder.expressionMap.parameters).includes(key)
|
||||||
|
) {
|
||||||
|
// 处理重复参数名
|
||||||
|
const uniqueKey = `${key}_${Date.now()}`;
|
||||||
|
queryBuilder.andWhere(`${alias}.${key} = :${uniqueKey}`, {
|
||||||
|
[uniqueKey]: value,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (!["purchaseDate", "startDate", "endDate"].includes(key)) {
|
||||||
|
queryBuilder.andWhere(`${alias}.${key} = :${key}`, {
|
||||||
|
[key]: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 执行分页查询
|
||||||
|
const [list, total] = await queryBuilder
|
||||||
|
.orderBy(`${alias}.createDate`, "DESC")
|
||||||
|
.skip((pageNumber - 1) * pageSize)
|
||||||
|
.take(pageSize)
|
||||||
|
.getManyAndCount();
|
||||||
|
|
||||||
|
return { list, total, pageSize, pageNumber };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列表接口
|
||||||
|
router.get("/list", async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const result = await queryRetailRecords({
|
||||||
|
req,
|
||||||
|
retailState: Number(req.query.retailState),
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
list: result.list,
|
||||||
|
pageNumber: result.pageNumber,
|
||||||
|
pageSize: result.pageSize,
|
||||||
|
total: result.total,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).json({
|
||||||
|
code: 500,
|
||||||
|
msg: err.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 查询接口
|
||||||
|
router.post("/query", async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const result = await queryRetailRecords({
|
||||||
|
req,
|
||||||
|
isQuery: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
list: result.list,
|
||||||
|
pageNumber: result.pageNumber,
|
||||||
|
pageSize: result.pageSize,
|
||||||
|
total: result.total,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).json({
|
||||||
|
code: 500,
|
||||||
|
msg: err.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/confirmCheckout", async (req, res) => {
|
||||||
|
let id = Number(req.body.id);
|
||||||
|
if (!id) {
|
||||||
|
return res.status(500).send({ code: 500, msg: "未传入结账id" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let connection = getConnection();
|
||||||
|
|
||||||
|
let deceasedRetailRep = connection.getRepository(DeceasedRetail);
|
||||||
|
let paymentRecordRep = connection.getRepository(CheckoutPayment);
|
||||||
|
|
||||||
|
let deceasedRetail = await deceasedRetailRep.findOne(id);
|
||||||
|
if (!deceasedRetail) {
|
||||||
|
return res.status(500).send({ code: 500, msg: "该记录不存在" });
|
||||||
|
}
|
||||||
|
|
||||||
|
let newPaymentRecord = new CheckoutPayment();
|
||||||
|
|
||||||
|
deceasedRetail.retailState = 1;
|
||||||
|
deceasedRetail.checkoutDate = new Date();
|
||||||
|
|
||||||
|
newPaymentRecord = Object.assign({}, req.body.currentPayment);
|
||||||
|
newPaymentRecord.checkoutRetailId = deceasedRetail.id;
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(deceasedRetail);
|
||||||
|
// await cancelRecordRep.save(newCancleRetail);
|
||||||
|
await paymentRecordRep.save(newPaymentRecord);
|
||||||
|
|
||||||
|
res
|
||||||
|
.status(200)
|
||||||
|
.send({ code: 200, data: deceasedRetail, msg: "结账成功!" });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
328
backEnd/src/router/cancle/cancleExamine.ts
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
|
||||||
|
import curd from "@/lib/curd/curd";
|
||||||
|
import DeceasedRetail from "@/entity/DeceasedRetail";
|
||||||
|
import CancelRetail from "@/entity/CancelRetail";
|
||||||
|
import Deceased from "@/entity/Deceased";
|
||||||
|
import PaymentRecord from "@/entity/Payment";
|
||||||
|
import CheckoutRetail from "@/entity/CheckoutRetail";
|
||||||
|
import CheckoutPaymentRecords from "@/entity/CheckoutPayment";
|
||||||
|
import CancelPayment from "@/entity/CancelPayment";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
async function getMoreInfor(result, type = 0) {
|
||||||
|
const deceasedRetailIds = result.list
|
||||||
|
.filter((item) => item.deceasedRetailId)
|
||||||
|
.map((item) => Number(item.deceasedRetailId));
|
||||||
|
|
||||||
|
const checkoutRetailIds = result.list
|
||||||
|
.filter((item) => item.checkoutRetailId)
|
||||||
|
.map((item) => Number(item.checkoutRetailId));
|
||||||
|
|
||||||
|
if (deceasedRetailIds.length) {
|
||||||
|
const deceasedRetails = await getConnection()
|
||||||
|
.getRepository(DeceasedRetail)
|
||||||
|
.createQueryBuilder("deceased_retail")
|
||||||
|
.where("deceased_retail.id IN (:...ids)", {
|
||||||
|
ids: deceasedRetailIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
const deceasedIds = Array.from(
|
||||||
|
new Set(deceasedRetails.map((item) => Number(item.deceasedId)))
|
||||||
|
);
|
||||||
|
let deceaseds = [];
|
||||||
|
|
||||||
|
if (deceasedIds.length) {
|
||||||
|
deceaseds = await getConnection()
|
||||||
|
.getRepository(Deceased)
|
||||||
|
.createQueryBuilder("deceased")
|
||||||
|
.where("deceased.id IN (:...ids)", {
|
||||||
|
ids: deceasedIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
}
|
||||||
|
|
||||||
|
let paymentRecords = [];
|
||||||
|
|
||||||
|
if (type === 0) {
|
||||||
|
paymentRecords = await getConnection()
|
||||||
|
.getRepository(CheckoutPaymentRecords)
|
||||||
|
.createQueryBuilder("paymentRecord")
|
||||||
|
.where("paymentRecord.checkout_retail_id IN (:...ids)", {
|
||||||
|
ids: deceasedRetailIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
let tempRec = await getConnection()
|
||||||
|
.getRepository(PaymentRecord)
|
||||||
|
.createQueryBuilder("paymentRecord")
|
||||||
|
.where("paymentRecord.deceased_retail_id IN (:...ids)", {
|
||||||
|
ids: deceasedRetailIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
paymentRecords = [...paymentRecords, ...tempRec];
|
||||||
|
} else {
|
||||||
|
let retailIds = result.list.map((item) => Number(item.id));
|
||||||
|
|
||||||
|
paymentRecords = await getConnection()
|
||||||
|
.getRepository(CancelPayment)
|
||||||
|
.createQueryBuilder("paymentRecord")
|
||||||
|
.where("paymentRecord.retail_id IN (:...ids)", {
|
||||||
|
ids: retailIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
}
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
let retail = deceasedRetails.find(
|
||||||
|
(fitem: any) => fitem.id === item.deceasedRetailId
|
||||||
|
);
|
||||||
|
|
||||||
|
let deceased = {};
|
||||||
|
if (retail) {
|
||||||
|
deceased = deceaseds.find((fitem) => fitem.id === retail.deceasedId);
|
||||||
|
}
|
||||||
|
let payment =
|
||||||
|
paymentRecords.find(
|
||||||
|
(fitem) => fitem.checkoutRetailId === item.deceasedRetailId
|
||||||
|
) ||
|
||||||
|
paymentRecords.find((fitem) => fitem.retailId === item.id) ||
|
||||||
|
paymentRecords.find(
|
||||||
|
(fitem) => fitem.deceasedRetailId === item.deceasedRetailId
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
retail,
|
||||||
|
deceased,
|
||||||
|
payment,
|
||||||
|
...item,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (checkoutRetailIds.length) {
|
||||||
|
const checkouitRetails = await getConnection()
|
||||||
|
.getRepository(CheckoutRetail)
|
||||||
|
.createQueryBuilder("checkout_retail")
|
||||||
|
.where("checkout_retail.id IN (:...ids)", {
|
||||||
|
ids: checkoutRetailIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
let deceaseds = [];
|
||||||
|
|
||||||
|
if (checkouitRetails.length) {
|
||||||
|
const checkoutRetailsIds = Array.from(
|
||||||
|
new Set(checkouitRetails.map((item) => Number(item.deceasedId)))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (checkoutRetailsIds.length) {
|
||||||
|
deceaseds = await getConnection()
|
||||||
|
.getRepository(Deceased)
|
||||||
|
.createQueryBuilder("deceased")
|
||||||
|
.where("deceased.id IN (:...ids)", {
|
||||||
|
ids: checkoutRetailsIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
}
|
||||||
|
|
||||||
|
const paymentRecords = await getConnection()
|
||||||
|
.getRepository(CheckoutPaymentRecords)
|
||||||
|
.createQueryBuilder("paymentRecord")
|
||||||
|
.where("paymentRecord.checkoutRetailId IN (:...ids)", {
|
||||||
|
ids: checkoutRetailIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
let retail = checkouitRetails.find(
|
||||||
|
(fitem: any) => fitem.id === item.checkoutRetailId
|
||||||
|
);
|
||||||
|
|
||||||
|
let deceased = deceaseds.find(
|
||||||
|
(fitem) => fitem.id === retail.deceasedId
|
||||||
|
);
|
||||||
|
|
||||||
|
let payment = paymentRecords.find(
|
||||||
|
(fitem) => fitem.checkoutRetailId === item.checkoutRetailId
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
retail,
|
||||||
|
deceased,
|
||||||
|
payment,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result: any = await curd({
|
||||||
|
entity: CancelRetail,
|
||||||
|
req,
|
||||||
|
params: {
|
||||||
|
examineState: 0,
|
||||||
|
},
|
||||||
|
}).queryList();
|
||||||
|
|
||||||
|
// console.log(result);
|
||||||
|
|
||||||
|
await getMoreInfor(result);
|
||||||
|
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 查询逝者列表(支持分页)
|
||||||
|
router.post("/query", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result = await curd({
|
||||||
|
entity: CancelRetail,
|
||||||
|
req,
|
||||||
|
params: {
|
||||||
|
...req.body,
|
||||||
|
},
|
||||||
|
}).queryList();
|
||||||
|
|
||||||
|
await getMoreInfor(result, 1);
|
||||||
|
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/cancel", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const deceaseRetailRep = connection.getRepository(DeceasedRetail);
|
||||||
|
const cancelRetailRep = connection.getRepository(CancelRetail);
|
||||||
|
|
||||||
|
let findDeceaseRetail = await deceaseRetailRep.findOne(
|
||||||
|
Number(req.body.deceasedRetailId)
|
||||||
|
);
|
||||||
|
let cancelRetail = new CancelRetail();
|
||||||
|
|
||||||
|
findDeceaseRetail.cancelState = 1;
|
||||||
|
|
||||||
|
cancelRetail = {
|
||||||
|
...cancelRetail,
|
||||||
|
...req.body.cancelForm,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 结账处理
|
||||||
|
cancelRetail.deceasedRetailId = findDeceaseRetail.id;
|
||||||
|
cancelRetail.cancelDate = new Date();
|
||||||
|
|
||||||
|
await deceaseRetailRep.save(findDeceaseRetail);
|
||||||
|
await cancelRetailRep.save(cancelRetail);
|
||||||
|
|
||||||
|
res.send({ code: 200, data: cancelRetail });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/examine", async (req, res) => {
|
||||||
|
let examineState = req.body.examineState;
|
||||||
|
let id = req.body.id;
|
||||||
|
let connection = getConnection();
|
||||||
|
|
||||||
|
if (examineState === 1) {
|
||||||
|
try {
|
||||||
|
let cancleRetailRep = connection.getRepository(CancelRetail);
|
||||||
|
let cancleRetail = await cancleRetailRep.findOne(id);
|
||||||
|
|
||||||
|
let cancelPaymentRep = connection.getRepository(CancelPayment);
|
||||||
|
let cancelPayment = new CancelPayment();
|
||||||
|
|
||||||
|
cancelPayment = { ...req.body.payment };
|
||||||
|
delete cancelPayment.id;
|
||||||
|
cancelPayment.retailId = cancleRetail.id;
|
||||||
|
|
||||||
|
await cancelPaymentRep.save(cancelPayment);
|
||||||
|
|
||||||
|
cancleRetail.examineState = 1;
|
||||||
|
cancleRetail.examineDate = new Date();
|
||||||
|
|
||||||
|
if (req.body.checkoutRetailId) {
|
||||||
|
let checkoutRetailRep = connection.getRepository(CheckoutRetail);
|
||||||
|
let checkoutRetail = await checkoutRetailRep.findOne(
|
||||||
|
req.body.checkoutRetailId
|
||||||
|
);
|
||||||
|
checkoutRetail.cancelState = 1;
|
||||||
|
|
||||||
|
await checkoutRetailRep.save(checkoutRetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.body.deceasedRetailId) {
|
||||||
|
let deceasedRetailRep = connection.getRepository(DeceasedRetail);
|
||||||
|
let deceasedRetail = await deceasedRetailRep.findOne(
|
||||||
|
req.body.deceasedRetailId
|
||||||
|
);
|
||||||
|
deceasedRetail.cancelState = 0;
|
||||||
|
deceasedRetail.retailState = 0;
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(deceasedRetail);
|
||||||
|
}
|
||||||
|
await cancleRetailRep.save(cancleRetail);
|
||||||
|
|
||||||
|
let paymentRep = connection.getRepository(PaymentRecord);
|
||||||
|
let findPaymeny = await paymentRep.findOne(req.body.payment.id);
|
||||||
|
|
||||||
|
if (findPaymeny) {
|
||||||
|
findPaymeny.cashAmount = 0;
|
||||||
|
findPaymeny.unionPayAmount = 0;
|
||||||
|
findPaymeny.cardAmount = 0;
|
||||||
|
findPaymeny.publicTransferAmount = 0;
|
||||||
|
findPaymeny.workshopPayment = 0;
|
||||||
|
await paymentRep.save(findPaymeny);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send({ code: 200, data: cancleRetail });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (examineState === 2) {
|
||||||
|
try {
|
||||||
|
let cancleRetailRep = getConnection().getRepository(CancelRetail);
|
||||||
|
let cancleRetail = await cancleRetailRep.findOne(id);
|
||||||
|
|
||||||
|
if (req.body.checkoutRetailId) {
|
||||||
|
let checkoutRetailRep = getConnection().getRepository(CheckoutRetail);
|
||||||
|
let checkoutRetail = await checkoutRetailRep.findOne(
|
||||||
|
req.body.checkoutRetailId
|
||||||
|
);
|
||||||
|
checkoutRetail.cancelState = 1;
|
||||||
|
|
||||||
|
await checkoutRetailRep.save(checkoutRetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.body.deceasedRetailId) {
|
||||||
|
let deceasedRetailRep = getConnection().getRepository(DeceasedRetail);
|
||||||
|
let deceasedRetail = await deceasedRetailRep.findOne(
|
||||||
|
req.body.deceasedRetailId
|
||||||
|
);
|
||||||
|
deceasedRetail.cancelState = 0;
|
||||||
|
deceasedRetail.retailState = 1;
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(deceasedRetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
await cancleRetailRep.remove(cancleRetail);
|
||||||
|
|
||||||
|
res.send({ code: 200, data: cancleRetail });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
50
backEnd/src/router/checkout/checkout.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import DeceasedRetail from "@/entity/DeceasedRetail";
|
||||||
|
import PaymentRecord from "@/entity/Payment";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.post("/deceasedCheckout", async (req, res) => {
|
||||||
|
let id = Number(req.body.id);
|
||||||
|
if (!id) {
|
||||||
|
return res.status(500).send({ code: 500, msg: "未传入结账id" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let connection = getConnection();
|
||||||
|
|
||||||
|
let deceasedRetailRep = connection.getRepository(DeceasedRetail);
|
||||||
|
let paymentRecordRep = connection.getRepository(PaymentRecord);
|
||||||
|
|
||||||
|
let deceasedRetail = await deceasedRetailRep.findOne(id);
|
||||||
|
|
||||||
|
if (!deceasedRetail)
|
||||||
|
return res.status(500).send({ code: 500, msg: "该记录不存在" });
|
||||||
|
|
||||||
|
let newPaymentRecord = await paymentRecordRep.findOne({
|
||||||
|
deceasedRetailId: deceasedRetail.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!newPaymentRecord) {
|
||||||
|
newPaymentRecord = new PaymentRecord();
|
||||||
|
}
|
||||||
|
|
||||||
|
deceasedRetail.retailState = 1;
|
||||||
|
deceasedRetail.checkoutDate = new Date();
|
||||||
|
|
||||||
|
newPaymentRecord = Object.assign(newPaymentRecord, req.body.currentPayment);
|
||||||
|
newPaymentRecord.deceasedRetailId = deceasedRetail.id;
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(deceasedRetail);
|
||||||
|
await paymentRecordRep.save(newPaymentRecord);
|
||||||
|
|
||||||
|
res
|
||||||
|
.status(200)
|
||||||
|
.send({ code: 200, data: deceasedRetail, msg: "结账成功!" });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
201
backEnd/src/router/deceased/deceased.ts
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import Deceased from "@/entity/Deceased";
|
||||||
|
import curd from "@/lib/curd/curd";
|
||||||
|
import DeceasedRetail from "@/entity/DeceasedRetail";
|
||||||
|
import { SeletedServiceList } from "@/entity/SeletedServiceList";
|
||||||
|
import { Request } from "express-serve-static-core";
|
||||||
|
import PaymentRecord from "@/entity/Payment";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// 查询逝者列表(支持分页)
|
||||||
|
router.post("/query", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result = await curd({ entity: Deceased, req }).queryList();
|
||||||
|
await getData(result, req);
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result = await curd({ entity: Deceased, req }).queryList();
|
||||||
|
await getData(result, req);
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加逝者
|
||||||
|
router.post("/add", async (req, res) => {
|
||||||
|
const { name, idNumber } = req.body;
|
||||||
|
|
||||||
|
if (!name || !idNumber) {
|
||||||
|
return res.send({ code: 400, msg: "逝者姓名和证件号码不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const deceasedRepository = connection.getRepository(Deceased);
|
||||||
|
const deceasedRetailRep = connection.getRepository(DeceasedRetail);
|
||||||
|
|
||||||
|
const tempServiceItems = req.body.services.map((item) => {
|
||||||
|
delete item.id;
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
req.body.serviceItems = "";
|
||||||
|
|
||||||
|
// 校验是否已存在相同证件号码的逝者
|
||||||
|
const existingDeceased = await deceasedRepository.findOne({
|
||||||
|
where: { idNumber },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingDeceased) {
|
||||||
|
return res.send({ code: 400, msg: "证件号码已存在,请勿重复添加!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const newDeceased = await curd({ entity: Deceased, req }).add();
|
||||||
|
let newDeceasedRetail = await curd({ entity: DeceasedRetail, req }).add();
|
||||||
|
|
||||||
|
if (tempServiceItems.length) {
|
||||||
|
tempServiceItems.forEach((item) => {
|
||||||
|
item.retailId = newDeceasedRetail.id;
|
||||||
|
|
||||||
|
delete item.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.save(tempServiceItems);
|
||||||
|
|
||||||
|
newDeceasedRetail.serviceItems = data.map((item) => item.id).join(",");
|
||||||
|
}
|
||||||
|
newDeceasedRetail.deceasedId = newDeceased.id;
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(newDeceasedRetail);
|
||||||
|
|
||||||
|
res.send({ code: 200, msg: "逝者信息添加成功", data: newDeceased });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新逝者信息
|
||||||
|
router.post("/update", async (req, res) => {
|
||||||
|
const { id, idNumber } = req.body;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "逝者ID不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const deceasedRepository = connection.getRepository(Deceased);
|
||||||
|
|
||||||
|
// 校验是否已存在相同证件号码的逝者(排除当前记录)
|
||||||
|
if (idNumber) {
|
||||||
|
const existingDeceased = await deceasedRepository.findOne({
|
||||||
|
where: { idNumber },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingDeceased && existingDeceased.id !== id) {
|
||||||
|
return res.send({ code: 400, msg: "证件号码已存在,请勿重复使用!" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedDeceased = await curd({ entity: Deceased, req }).update();
|
||||||
|
res.send({ code: 200, msg: "逝者信息更新成功", data: updatedDeceased });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 删除逝者信息
|
||||||
|
router.get("/delete", async (req, res) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "逝者ID不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await curd({ entity: Deceased, req }).delete();
|
||||||
|
res.send({ code: 200, msg: "逝者信息删除成功" });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function getData(result, req: Request) {
|
||||||
|
let type = req.query.type ?? req.body.type;
|
||||||
|
if (!type && type !== 0) type = 0;
|
||||||
|
|
||||||
|
const deceasedId = Array.from(
|
||||||
|
new Set(result.list.map((item) => Number(item.deceasedId)))
|
||||||
|
);
|
||||||
|
|
||||||
|
const deceasedIds = Array.from(
|
||||||
|
new Set(result.list.map((item) => Number(item.id)))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (deceasedId.length) {
|
||||||
|
const reatialList = await getConnection()
|
||||||
|
.getRepository(DeceasedRetail)
|
||||||
|
.createQueryBuilder("DeceasedRetail")
|
||||||
|
.where("DeceasedRetail.deceased_id IN (:...ids)", {
|
||||||
|
ids: deceasedIds,
|
||||||
|
})
|
||||||
|
.andWhere("DeceasedRetail.retail_type = :retailType", {
|
||||||
|
retailType: type,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
if (reatialList.length) {
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
deceased: { ...item },
|
||||||
|
retail: reatialList.find(
|
||||||
|
(fitem: any) => fitem.deceasedId === item.id
|
||||||
|
),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let retailIds = reatialList.map((item) => item.id);
|
||||||
|
|
||||||
|
if (retailIds.length) {
|
||||||
|
const serviceList = await getConnection()
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("SeletedServiceList")
|
||||||
|
.where("SeletedServiceList.retail_id IN (:...retailIds)", {
|
||||||
|
retailIds: retailIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
if (serviceList.length) {
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
let retailId = reatialList.find(
|
||||||
|
(fitem) => fitem.deceasedId === item.id
|
||||||
|
)?.id;
|
||||||
|
|
||||||
|
let services = serviceList.filter(
|
||||||
|
(fitem) => fitem.retailId === retailId
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
serviceItems: services.map((mitem) => mitem.id.toString()),
|
||||||
|
services: services,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default router;
|
||||||
484
backEnd/src/router/deceasedRetail/deceasedRetail.ts
Normal file
@@ -0,0 +1,484 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import DeceasedRetail from "../../entity/DeceasedRetail";
|
||||||
|
import curd from "@/lib/curd/curd";
|
||||||
|
import SeletedServiceList from "@/entity/SeletedServiceList";
|
||||||
|
import Deceased from "@/entity/Deceased";
|
||||||
|
import PaymentRecord from "@/entity/Payment";
|
||||||
|
import parseRangDate, { getPaginationParams } from "@/util/globalMethods";
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
async function GetData(result) {
|
||||||
|
const ids = Array.from(
|
||||||
|
new Set(result.list.map((item) => Number(item.deceasedId)))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ids.length) {
|
||||||
|
const manyResult = await getConnection()
|
||||||
|
.getRepository(Deceased)
|
||||||
|
.createQueryBuilder("deceased")
|
||||||
|
.where("deceased.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
let findData = manyResult.find(
|
||||||
|
(fitem: any) => fitem.id === item.deceasedId
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
deceased: findData,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let paymentIds = result.list
|
||||||
|
.filter((item) => item.retailState === 1)
|
||||||
|
.map((item) => item.id);
|
||||||
|
if (paymentIds.length) {
|
||||||
|
let manyResult = await getConnection()
|
||||||
|
.getRepository(PaymentRecord)
|
||||||
|
.createQueryBuilder("PaymentRecord")
|
||||||
|
.where("PaymentRecord.deceased_retail_id IN (:...ids)", {
|
||||||
|
ids: paymentIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
payment: manyResult.find((fitem) => fitem.deceasedRetailId === item.id),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
router.post("/query", async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
pageNumber = 1,
|
||||||
|
pageSize = 10,
|
||||||
|
deceased = {},
|
||||||
|
retail = {},
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
// 参数校验
|
||||||
|
const connection = getConnection();
|
||||||
|
const queryBuilder = connection
|
||||||
|
.getRepository(DeceasedRetail)
|
||||||
|
.createQueryBuilder("retail")
|
||||||
|
.leftJoinAndMapOne(
|
||||||
|
"retail.deceased",
|
||||||
|
Deceased,
|
||||||
|
"deceased",
|
||||||
|
"deceased.id = retail.deceased_id"
|
||||||
|
)
|
||||||
|
.leftJoinAndMapOne(
|
||||||
|
"retail.payment",
|
||||||
|
PaymentRecord,
|
||||||
|
"payment",
|
||||||
|
"payment.deceased_retail_id = retail.id"
|
||||||
|
)
|
||||||
|
.where(`retail.cancel_state = 0`)
|
||||||
|
.andWhere("retail.retail_type = :retailType", {
|
||||||
|
retailType: retail.retailType ?? 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
req.body.startDate = retail.startDate;
|
||||||
|
req.body.endDate = retail.endDate;
|
||||||
|
let { startDate, endDate } = parseRangDate(req);
|
||||||
|
if (retail.retailType === 2) {
|
||||||
|
if (retail.familyName) {
|
||||||
|
queryBuilder.andWhere("retail.familyName LIKE :familyName", {
|
||||||
|
familyName: `%${retail.familyName}%`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (deceased.name) {
|
||||||
|
queryBuilder.andWhere("retail.deceased_Name LIKE :name", {
|
||||||
|
name: `%${deceased.name}%`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retail.retailType === 1) {
|
||||||
|
if (deceased.name) {
|
||||||
|
queryBuilder.andWhere("deceased.name LIKE :name", {
|
||||||
|
name: `%${deceased.name}%`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (retail.familyName) {
|
||||||
|
queryBuilder.andWhere("retail.familyName LIKE :familyName", {
|
||||||
|
familyName: `%${retail.familyName}%`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (startDate && endDate) {
|
||||||
|
queryBuilder
|
||||||
|
.andWhere(`retail.purchaseDate BETWEEN :start AND :end`)
|
||||||
|
.setParameters({ start: startDate, end: endDate });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retail.guide) {
|
||||||
|
queryBuilder.andWhere(`retail.guide LIKE :guide`, {
|
||||||
|
guide: retail.guide,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行分页查询
|
||||||
|
const [list, total] = await queryBuilder
|
||||||
|
.orderBy("retail.createDate", "DESC")
|
||||||
|
.skip((pageNumber - 1) * pageSize)
|
||||||
|
.take(pageSize)
|
||||||
|
.getManyAndCount();
|
||||||
|
|
||||||
|
let result = {
|
||||||
|
list,
|
||||||
|
total,
|
||||||
|
pageSize,
|
||||||
|
pageNumber,
|
||||||
|
};
|
||||||
|
await GetData(result);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
code: 200,
|
||||||
|
data: result,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("查询失败:", err);
|
||||||
|
res.status(500).json({
|
||||||
|
code: 500,
|
||||||
|
msg: process.env.NODE_ENV === "production" ? "服务器错误" : err.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
try {
|
||||||
|
let { retailType } = req.method === "GET" ? req.query : req.body;
|
||||||
|
let queryBuilder = getConnection()
|
||||||
|
.getRepository(DeceasedRetail)
|
||||||
|
.createQueryBuilder("dr")
|
||||||
|
.where(`dr.retailType=${retailType}`)
|
||||||
|
.andWhere(`dr.cancelState = 0`);
|
||||||
|
|
||||||
|
const { pageSize, pageNumber } = getPaginationParams(req);
|
||||||
|
|
||||||
|
let [list, total] = await queryBuilder
|
||||||
|
.orderBy("dr.createDate", "DESC")
|
||||||
|
.skip((pageNumber - 1) * pageSize)
|
||||||
|
.take(pageSize)
|
||||||
|
.getManyAndCount();
|
||||||
|
let result = {
|
||||||
|
list,
|
||||||
|
pageNumber,
|
||||||
|
pageSize,
|
||||||
|
total,
|
||||||
|
};
|
||||||
|
|
||||||
|
await GetData(result);
|
||||||
|
res.status(200).send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retailId: 销售单ID
|
||||||
|
* deceasedId: 人的ID,且必须传retailType
|
||||||
|
*/
|
||||||
|
router.get("/selected-service", async (req, res) => {
|
||||||
|
let retailId = req.query.retailId;
|
||||||
|
let deceasedId = req.query.deceasedId;
|
||||||
|
let retailType = req.query.retailType;
|
||||||
|
try {
|
||||||
|
let retail;
|
||||||
|
if (retailId) {
|
||||||
|
if (retailType && Number(retailType) === 2) {
|
||||||
|
retail = await getConnection()
|
||||||
|
.getRepository(DeceasedRetail)
|
||||||
|
.findOne({
|
||||||
|
where: {
|
||||||
|
id: Number(retailId),
|
||||||
|
retailType,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
retail = await getConnection()
|
||||||
|
.getRepository(DeceasedRetail)
|
||||||
|
.findOne(Number(retailId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deceasedId) {
|
||||||
|
retail = await getConnection()
|
||||||
|
.getRepository(DeceasedRetail)
|
||||||
|
.createQueryBuilder("deceasedRetail")
|
||||||
|
.where("deceasedRetail.retail_type = :retailType", {
|
||||||
|
retailType,
|
||||||
|
})
|
||||||
|
.andWhere("deceasedRetail.deceased_id = :deceasedId", {
|
||||||
|
deceasedId,
|
||||||
|
})
|
||||||
|
.getOne();
|
||||||
|
}
|
||||||
|
if (!retail) return res.status(200).send({ code: 200, data: { list: [] } });
|
||||||
|
|
||||||
|
const ids = retail.serviceItems
|
||||||
|
? retail.serviceItems.split(",").map((id) => Number(id))
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (!ids.length)
|
||||||
|
return res.status(200).send({ code: 200, data: { list: [] } });
|
||||||
|
const result = await getConnection()
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("seleted_service_list")
|
||||||
|
.where("seleted_service_list.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
res.status(200).send({ code: 200, data: { list: result } });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/checkout", async (req, res) => {
|
||||||
|
let { id } = req.query;
|
||||||
|
if (!id) {
|
||||||
|
return res.status(500).send({ code: 500, msg: "未传入结账id" });
|
||||||
|
}
|
||||||
|
|
||||||
|
let deceasedRetailRep = getConnection().getRepository(DeceasedRetail);
|
||||||
|
let deceasedRetail = await deceasedRetailRep.findOne(Number(id));
|
||||||
|
|
||||||
|
if (!deceasedRetail)
|
||||||
|
return res.status(500).send({ code: 500, msg: "该记录不存在" });
|
||||||
|
|
||||||
|
deceasedRetail.retailState = 1;
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(deceasedRetail);
|
||||||
|
|
||||||
|
res.status(200).send({ code: 200, data: deceasedRetail, msg: "结账成功!" });
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加逝者零售
|
||||||
|
router.post("/add", async (req, res) => {
|
||||||
|
delete req.body.id;
|
||||||
|
const connection = getConnection();
|
||||||
|
try {
|
||||||
|
const tempServiceItems = req.body.services.map((item) => {
|
||||||
|
delete item.id;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
req.body.serviceItems = "";
|
||||||
|
|
||||||
|
const deceasedRetailRep = connection.getRepository(DeceasedRetail);
|
||||||
|
const newDeceasedRetail = await curd({ entity: DeceasedRetail, req }).add();
|
||||||
|
|
||||||
|
if (tempServiceItems.length) {
|
||||||
|
tempServiceItems.forEach((item) => {
|
||||||
|
item.retailId = newDeceasedRetail.id;
|
||||||
|
});
|
||||||
|
let executeData = await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.save(tempServiceItems);
|
||||||
|
|
||||||
|
newDeceasedRetail.serviceItems = executeData
|
||||||
|
.map((item) => item.id)
|
||||||
|
.join(",");
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(newDeceasedRetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send({ code: 200, msg: "逝者零售添加成功", data: newDeceasedRetail });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/updateRetail", async (req, res) => {
|
||||||
|
const connection = getConnection();
|
||||||
|
try {
|
||||||
|
const tempServiceItems = req.body.services.map((item) => {
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
req.body.serviceItems = "";
|
||||||
|
|
||||||
|
const deceasedRetailRep = connection.getRepository(DeceasedRetail);
|
||||||
|
let newDeceasedRetail = await deceasedRetailRep.findOne({
|
||||||
|
id: req.body?.retail?.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!newDeceasedRetail) {
|
||||||
|
newDeceasedRetail = await deceasedRetailRep.findOne({
|
||||||
|
where: { deceasedId: req.body.deceasedId, retailType: 0 },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempServiceItems.length) {
|
||||||
|
tempServiceItems.forEach((item) => {
|
||||||
|
item.retailId = newDeceasedRetail.id;
|
||||||
|
item.updateDate = new Date();
|
||||||
|
item.createDate = new Date();
|
||||||
|
});
|
||||||
|
|
||||||
|
const ids = newDeceasedRetail.serviceItems
|
||||||
|
.split(",")
|
||||||
|
.map((id) => Number(id));
|
||||||
|
if (ids.length) {
|
||||||
|
await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("seleted_service_list")
|
||||||
|
.where("seleted_service_list.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.delete()
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
let executeData = await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.save(tempServiceItems);
|
||||||
|
|
||||||
|
newDeceasedRetail.salesAmount = req.body.salesAmount;
|
||||||
|
|
||||||
|
newDeceasedRetail.serviceItems = executeData
|
||||||
|
.map((item) => item.id)
|
||||||
|
.join(",");
|
||||||
|
|
||||||
|
// 保存人
|
||||||
|
let deceased = await connection
|
||||||
|
.getRepository(Deceased)
|
||||||
|
.findOne(req.body.id);
|
||||||
|
if (deceased) {
|
||||||
|
deceased = { ...deceased, ...req.body.deceased };
|
||||||
|
deceased.salesAmount = newDeceasedRetail.salesAmount;
|
||||||
|
|
||||||
|
await connection.getRepository(Deceased).save(deceased);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const ids = newDeceasedRetail.serviceItems
|
||||||
|
.split(",")
|
||||||
|
.map((id) => Number(id));
|
||||||
|
if (ids.length) {
|
||||||
|
await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("seleted_service_list")
|
||||||
|
.where("seleted_service_list.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.delete()
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
newDeceasedRetail.serviceItems = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(newDeceasedRetail);
|
||||||
|
|
||||||
|
res.send({ code: 200, msg: "逝者服务单修改成功", data: newDeceasedRetail });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新逝者信息
|
||||||
|
router.post("/update", async (req, res) => {
|
||||||
|
const id = Number(req.body.id);
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "逝者ID不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const deceasedRepository = connection.getRepository(DeceasedRetail);
|
||||||
|
const deceasedRep = connection.getRepository(Deceased);
|
||||||
|
|
||||||
|
let services = req.body.retail?.services || req.body.services;
|
||||||
|
const tempServiceItems = services.map((item) => {
|
||||||
|
delete item.id;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
let findData = await deceasedRepository.findOne(id);
|
||||||
|
|
||||||
|
let decease = await deceasedRep.findOne(Number(findData.deceasedId));
|
||||||
|
|
||||||
|
const ids = findData.serviceItems.split(",").map((id) => Number(id));
|
||||||
|
if (ids.length) {
|
||||||
|
await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("seleted_service_list")
|
||||||
|
.where("seleted_service_list.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.delete()
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
findData = { ...findData, ...req.body };
|
||||||
|
if (tempServiceItems.length) {
|
||||||
|
tempServiceItems.forEach((item) => {
|
||||||
|
item.retailId = id;
|
||||||
|
item.hasDeceased = 0;
|
||||||
|
item.updateDate = new Date();
|
||||||
|
item.createDate = new Date();
|
||||||
|
});
|
||||||
|
let executeData = await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.save(tempServiceItems);
|
||||||
|
|
||||||
|
findData.serviceItems = executeData.map((item) => item.id).join(",");
|
||||||
|
}
|
||||||
|
let newDeceased: Deceased = { ...req.body };
|
||||||
|
delete newDeceased.id;
|
||||||
|
|
||||||
|
decease = { ...decease, ...newDeceased };
|
||||||
|
|
||||||
|
await deceasedRep.save(decease);
|
||||||
|
await deceasedRepository.save(findData);
|
||||||
|
|
||||||
|
res.send({ code: 200, msg: "更新成功", data: findData });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 删除逝者信息
|
||||||
|
router.get("/delete", async (req, res) => {
|
||||||
|
const id = Number(req.query.id);
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "数据ID不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const deceasedRepository = connection.getRepository(DeceasedRetail);
|
||||||
|
|
||||||
|
const findData = await deceasedRepository.findOne(id);
|
||||||
|
|
||||||
|
const ids = findData.serviceItems.split(",").map((id) => Number(id));
|
||||||
|
if (ids.length) {
|
||||||
|
await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("seleted_service_list")
|
||||||
|
.where("seleted_service_list.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.delete()
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
await deceasedRepository.remove(findData);
|
||||||
|
|
||||||
|
res.send({ code: 200, msg: "删除成功!" });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
75
backEnd/src/router/index.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import login from "./login/login";
|
||||||
|
import user from "./user/user";
|
||||||
|
import systemMenue from "./system-menue/system-menue";
|
||||||
|
import role from "./role/role";
|
||||||
|
import deceased from "./deceased/deceased";
|
||||||
|
import serviceItem from "./serviceList/serviceItem";
|
||||||
|
import serviceCategory from "./serviceList/serviceCategory";
|
||||||
|
import deceasedRetail from "./deceasedRetail/deceasedRetail";
|
||||||
|
import checkout from "./checkout/checkout";
|
||||||
|
import retailCheckout from "./retailCheckout/retailCheckout";
|
||||||
|
import noDeceasedRetail from "./noDeceasedRetail/noDeceasedRetail";
|
||||||
|
import cancleExamine from "./cancle/cancleExamine";
|
||||||
|
import CheckoutRetail from "./CheckoutRetail/CheckoutRetail";
|
||||||
|
import publicList from "./public/public";
|
||||||
|
import Stats from "./stats/stats";
|
||||||
|
|
||||||
|
let jwt = require("jsonwebtoken");
|
||||||
|
|
||||||
|
let router = express.Router();
|
||||||
|
const secretKey = "myNameIsLiJiaTu";
|
||||||
|
|
||||||
|
// 统一请求入口
|
||||||
|
router.use("/", (req, res, next) => {
|
||||||
|
const token = req.headers.authorization;
|
||||||
|
const refreshToken = req.headers.refreshtoken;
|
||||||
|
// 非登录并且无token证明用户未登录,禁止操作,不需要这个,注释即可
|
||||||
|
if (!token && !refreshToken && req.path !== "/login")
|
||||||
|
return res.send({ code: 401, msg: "未登录,禁止操作访问!" });
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
jwt.verify(token, secretKey, (err, decoded) => {
|
||||||
|
if (err) {
|
||||||
|
if (!refreshToken) {
|
||||||
|
return res.status(401).send({ code: 401, msg: "请重新登录" });
|
||||||
|
}
|
||||||
|
jwt.verify(refreshToken, secretKey, (refErr, refDecoded) => {
|
||||||
|
if (refErr) {
|
||||||
|
return res
|
||||||
|
.status(401)
|
||||||
|
.send({ code: 401, msg: "登录已失效,请重新登录。" });
|
||||||
|
} else {
|
||||||
|
let userId = refDecoded.userId;
|
||||||
|
const newToken = jwt.sign({ userId }, secretKey, {
|
||||||
|
expiresIn: "1h",
|
||||||
|
});
|
||||||
|
res.setHeader("refreshToken", newToken);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
router.use("/login", login);
|
||||||
|
router.use("/user", user);
|
||||||
|
router.use("/system-menue", systemMenue);
|
||||||
|
router.use("/role", role);
|
||||||
|
router.use("/public/", publicList);
|
||||||
|
router.use("/deceased", deceased);
|
||||||
|
router.use("/deceased-retail", deceasedRetail);
|
||||||
|
router.use("/service-item", serviceItem);
|
||||||
|
router.use("/service-category", serviceCategory);
|
||||||
|
router.use("/checkout", checkout);
|
||||||
|
router.use("/retail-checkout", retailCheckout);
|
||||||
|
router.use("/no-deceased-retail", noDeceasedRetail);
|
||||||
|
router.use("/cancel", cancleExamine);
|
||||||
|
router.use("/checkout-retail", CheckoutRetail);
|
||||||
|
router.use("/stats", Stats);
|
||||||
|
|
||||||
|
export default router;
|
||||||
117
backEnd/src/router/login/login.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import User from "../../entity/User";
|
||||||
|
import { Role } from "../../entity/Role";
|
||||||
|
import { SystemMenue } from "../../entity/SystemMenue";
|
||||||
|
import menueToTree from "../../lib/menueToTree";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
let jwt = require("jsonwebtoken");
|
||||||
|
|
||||||
|
const secretKey = "myNameIsLiJiaTu";
|
||||||
|
|
||||||
|
// 递归获取所有父级菜单的ID
|
||||||
|
async function getAllParentIds(menuIds: number[]): Promise<number[]> {
|
||||||
|
const parentIds = new Set<number>();
|
||||||
|
|
||||||
|
const getParents = async (id: number) => {
|
||||||
|
let menueRep = getConnection().getRepository(SystemMenue);
|
||||||
|
const menu = await menueRep.findOne({ where: { id } });
|
||||||
|
if (menu && menu.parentId !== 0) {
|
||||||
|
parentIds.add(menu.parentId);
|
||||||
|
await getParents(menu.parentId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await Promise.all(menuIds.map((id) => getParents(id)));
|
||||||
|
return Array.from(parentIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
router.post("/", async (req: Request, res: Response) => {
|
||||||
|
const { name, pwd } = req.body;
|
||||||
|
|
||||||
|
const connection = getConnection();
|
||||||
|
const user = connection.getRepository(User);
|
||||||
|
if (!(await user.findAndCount())[0].length && name === "admin") {
|
||||||
|
let userInstance = new User();
|
||||||
|
userInstance = {
|
||||||
|
...userInstance,
|
||||||
|
name: "admin",
|
||||||
|
pwd: "E10ADC3949BA59ABBE56E057F20F883E",
|
||||||
|
role: "1",
|
||||||
|
userState: 1,
|
||||||
|
};
|
||||||
|
userInstance.createDate = userInstance.createDate || new Date();
|
||||||
|
userInstance.updateDate = userInstance.updateDate || new Date();
|
||||||
|
|
||||||
|
await connection.getRepository(User).save(userInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
const findUser = await user.findOne({ name });
|
||||||
|
if (!findUser) return res.send("该用户不存在,请检查!");
|
||||||
|
|
||||||
|
if (findUser && findUser.pwd !== pwd) return res.send("密码错误,请检查!");
|
||||||
|
if (findUser.userState === 0 && findUser.name !== "admin")
|
||||||
|
return res.send({ code: 500, msg: "该账号被禁止使用,请联系管理员!" });
|
||||||
|
|
||||||
|
let userRole = findUser.role;
|
||||||
|
let roleRep = connection.getRepository(Role);
|
||||||
|
|
||||||
|
if (findUser.name === "admin") {
|
||||||
|
let role = await roleRep.findOne({ where: { id: Number(userRole) } });
|
||||||
|
role.values = (
|
||||||
|
await connection.getRepository(SystemMenue).findAndCount()
|
||||||
|
)[0]
|
||||||
|
.map((item) => item.id.toString())
|
||||||
|
.join(",");
|
||||||
|
if (role.values.length !== findUser.role.length) {
|
||||||
|
await roleRep.save(role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let roleRes = await roleRep
|
||||||
|
.createQueryBuilder("role")
|
||||||
|
.where("role.id IN (:...userRole)", { userRole: userRole.split(",") })
|
||||||
|
.getOne();
|
||||||
|
if (roleRes) {
|
||||||
|
let menueRep = connection.getRepository(SystemMenue);
|
||||||
|
// 在原有查询中增加父级查询
|
||||||
|
const selectedMenuIds = roleRes.values.split(",").map(Number); // [34,33,24]
|
||||||
|
const parentIds = await getAllParentIds(selectedMenuIds); // 获取所有父级ID(如26)
|
||||||
|
|
||||||
|
const finalMenuIds = Array.from(
|
||||||
|
new Set([...selectedMenuIds, ...parentIds])
|
||||||
|
); // 合并选中的ID和父级ID
|
||||||
|
|
||||||
|
let menueList = await menueRep
|
||||||
|
.createQueryBuilder("system_menue")
|
||||||
|
.where("system_menue.id IN (:...menue)", { menue: finalMenuIds })
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
findUser["routerMenue"] = menueToTree(menueList);
|
||||||
|
} else {
|
||||||
|
findUser["routerMenue"] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录成功,生成 JWT
|
||||||
|
const token = jwt.sign({ userId: findUser.id }, secretKey, {
|
||||||
|
expiresIn: "1h",
|
||||||
|
});
|
||||||
|
const refreshToken = jwt.sign({ userId: findUser.id }, secretKey, {
|
||||||
|
expiresIn: "1d",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 过滤密码
|
||||||
|
delete findUser.pwd;
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
msg: "登录成功!",
|
||||||
|
data: {
|
||||||
|
token: "Bearer " + token,
|
||||||
|
refreshToken,
|
||||||
|
user: findUser,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
212
backEnd/src/router/noDeceasedRetail/noDeceasedRetail.ts
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection, getRepository } from "typeorm";
|
||||||
|
import DeceasedRetail from "../../entity/DeceasedRetail";
|
||||||
|
import curd from "@/lib/curd/curd";
|
||||||
|
import SeletedServiceList from "@/entity/SeletedServiceList";
|
||||||
|
import Deceased from "@/entity/Deceased";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
async function GetData(result) {
|
||||||
|
const ids = Array.from(
|
||||||
|
new Set(result.list.map((item) => Number(item.deceasedId)))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ids.length) {
|
||||||
|
const manyResult = await getConnection()
|
||||||
|
.getRepository(Deceased)
|
||||||
|
.createQueryBuilder("deceased")
|
||||||
|
.where("deceased.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
let findData = manyResult.find(
|
||||||
|
(fitem: any) => fitem.id === item.deceasedId
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...findData,
|
||||||
|
...item,
|
||||||
|
deceased: findData,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
router.post("/query", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result = await curd({
|
||||||
|
entity: DeceasedRetail,
|
||||||
|
req,
|
||||||
|
params: {
|
||||||
|
retailType: 2,
|
||||||
|
},
|
||||||
|
}).queryList();
|
||||||
|
await GetData(result);
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result: any = await curd({
|
||||||
|
entity: DeceasedRetail,
|
||||||
|
req,
|
||||||
|
params: {
|
||||||
|
retailType: 2,
|
||||||
|
},
|
||||||
|
}).queryList();
|
||||||
|
await GetData(result);
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/checkout", async (req, res) => {
|
||||||
|
let { id } = req.query;
|
||||||
|
if (!id) {
|
||||||
|
return res.status(500).send({ code: 500, msg: "未传入结账id" });
|
||||||
|
}
|
||||||
|
|
||||||
|
let deceasedRetailRep = getConnection().getRepository(DeceasedRetail);
|
||||||
|
let deceasedRetail = await deceasedRetailRep.findOne(Number(id));
|
||||||
|
|
||||||
|
if (!deceasedRetail)
|
||||||
|
return res.status(500).send({ code: 500, msg: "该记录不存在" });
|
||||||
|
|
||||||
|
deceasedRetail.retailState = 1;
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(deceasedRetail);
|
||||||
|
|
||||||
|
res.status(200).send({ code: 200, data: deceasedRetail, msg: "结账成功!" });
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/add", async (req, res) => {
|
||||||
|
delete req.body.id;
|
||||||
|
const connection = getConnection();
|
||||||
|
try {
|
||||||
|
const tempServiceItems = req.body.services.map((item) => {
|
||||||
|
delete item.id;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
req.body.serviceItems = "";
|
||||||
|
|
||||||
|
const deceasedRetailRep = connection.getRepository(DeceasedRetail);
|
||||||
|
let newDeceasedRetail = new DeceasedRetail();
|
||||||
|
|
||||||
|
newDeceasedRetail = Object.assign(newDeceasedRetail, req.body);
|
||||||
|
newDeceasedRetail.retailType = 2;
|
||||||
|
|
||||||
|
if (tempServiceItems.length) {
|
||||||
|
tempServiceItems.forEach((item) => {
|
||||||
|
item.retailId = newDeceasedRetail.id;
|
||||||
|
item.hasDeceased = 0;
|
||||||
|
});
|
||||||
|
let executeData = await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.save(tempServiceItems);
|
||||||
|
|
||||||
|
newDeceasedRetail.serviceItems = executeData
|
||||||
|
.map((item) => item.id)
|
||||||
|
.join(",");
|
||||||
|
|
||||||
|
await deceasedRetailRep.save(newDeceasedRetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send({ code: 200, msg: "添加成功", data: newDeceasedRetail });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/update", async (req, res) => {
|
||||||
|
const id = Number(req.body.id);
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "逝者ID不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const deceasedRepository = connection.getRepository(DeceasedRetail);
|
||||||
|
|
||||||
|
const tempServiceItems = req.body.services.map((item) => {
|
||||||
|
delete item.id;
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
let findData = await deceasedRepository.findOne(id);
|
||||||
|
|
||||||
|
const ids = findData.serviceItems.split(",").map((id) => Number(id));
|
||||||
|
if (ids.length) {
|
||||||
|
await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("seleted_service_list")
|
||||||
|
.where("seleted_service_list.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.delete()
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
findData = { ...findData, ...req.body };
|
||||||
|
if (tempServiceItems.length) {
|
||||||
|
tempServiceItems.forEach((item) => {
|
||||||
|
item.retailId = id;
|
||||||
|
item.hasDeceased = 0;
|
||||||
|
item.updateDate = new Date();
|
||||||
|
item.createDate = new Date();
|
||||||
|
});
|
||||||
|
let executeData = await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.save(tempServiceItems);
|
||||||
|
|
||||||
|
findData.serviceItems = executeData.map((item) => item.id).join(",");
|
||||||
|
|
||||||
|
await deceasedRepository.save(findData);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send({ code: 200, msg: "更新成功", data: findData });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/delete", async (req, res) => {
|
||||||
|
const id = Number(req.query.id);
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "数据ID不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const deceasedRepository = connection.getRepository(DeceasedRetail);
|
||||||
|
|
||||||
|
const findData = await deceasedRepository.findOne(id);
|
||||||
|
|
||||||
|
const ids = findData.serviceItems.split(",").map((id) => Number(id));
|
||||||
|
if (ids.length) {
|
||||||
|
await connection
|
||||||
|
.getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("seleted_service_list")
|
||||||
|
.where("seleted_service_list.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.delete()
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
await deceasedRepository.remove(findData);
|
||||||
|
|
||||||
|
res.send({ code: 200, msg: "删除成功!" });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
65
backEnd/src/router/public/public.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import User from "../../entity/User";
|
||||||
|
import { Role } from "@/entity/Role";
|
||||||
|
|
||||||
|
import ServiceCategory from "@/entity/ServiceCategory"; // 请确保路径正确
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/guide", async (req, res) => {
|
||||||
|
let roleRep = getConnection().getRepository(Role);
|
||||||
|
let guide1ID = (await roleRep.findOne({ name: "服务部" })).id;
|
||||||
|
|
||||||
|
let guideIds = [guide1ID]
|
||||||
|
.filter((item) => item)
|
||||||
|
.map((item) => item.toString());
|
||||||
|
let userList = await getConnection()
|
||||||
|
.getRepository(User)
|
||||||
|
.createQueryBuilder("user")
|
||||||
|
.where("user.role IN (:...ids)", {
|
||||||
|
ids: guideIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
data: userList.map((item) => {
|
||||||
|
return {
|
||||||
|
value: item.name,
|
||||||
|
label: item.name,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/service-categories", async (req, res) => {
|
||||||
|
try {
|
||||||
|
// 获取服务分类Repository
|
||||||
|
const categoryRepo = getConnection().getRepository(ServiceCategory);
|
||||||
|
|
||||||
|
// 查询所有分类(可按需要添加排序)
|
||||||
|
const categories = await categoryRepo.find({
|
||||||
|
order: { createDate: "DESC" }, // 按创建时间倒序
|
||||||
|
});
|
||||||
|
|
||||||
|
// 格式化返回数据
|
||||||
|
return res.status(200).json({
|
||||||
|
code: 200,
|
||||||
|
data: categories.map((item) => ({
|
||||||
|
value: item.id, // 使用ID作为值
|
||||||
|
label: item.name, // 显示分类名称
|
||||||
|
// 可根据需要添加额外字段
|
||||||
|
name: item.name,
|
||||||
|
// parentId: item.parentId
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
return res.status(500).json({
|
||||||
|
code: 500,
|
||||||
|
msg: "获取服务分类失败,请稍后重试",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
130
backEnd/src/router/retailCheckout/retailCheckout.ts
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import ServiceItem from "../../entity/ServiceItem";
|
||||||
|
import curd from "@/lib/curd/curd";
|
||||||
|
import DeceasedRetail from "@/entity/DeceasedRetail";
|
||||||
|
import Deceased from "@/entity/Deceased";
|
||||||
|
import noDeceasedRetail from "@/entity/noDeceasedRetail";
|
||||||
|
import PaymentRecord from "@/entity/Payment";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
async function GetData(result) {
|
||||||
|
let paymentIds = result.list
|
||||||
|
.filter((item) => item.retailState === 1)
|
||||||
|
.map((item) => item.id);
|
||||||
|
if (paymentIds.length) {
|
||||||
|
let manyResult = await getConnection()
|
||||||
|
.getRepository(PaymentRecord)
|
||||||
|
.createQueryBuilder("PaymentRecord")
|
||||||
|
.where("PaymentRecord.deceased_retail_id IN (:...ids)", {
|
||||||
|
ids: paymentIds,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
payment: manyResult.find((fitem) => fitem.deceasedRetailId === item.id),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
let retailType = Number(req.query.retailType || 0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let result = await curd({
|
||||||
|
entity: DeceasedRetail,
|
||||||
|
params: {
|
||||||
|
cancelState: 0,
|
||||||
|
retailType,
|
||||||
|
...req.body,
|
||||||
|
},
|
||||||
|
req,
|
||||||
|
}).queryList();
|
||||||
|
|
||||||
|
if (retailType === 1) {
|
||||||
|
const ids = Array.from(
|
||||||
|
new Set(result.list.map((item) => Number(item.deceasedId)))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ids.length) {
|
||||||
|
const manyResult = await getConnection()
|
||||||
|
.getRepository(Deceased)
|
||||||
|
.createQueryBuilder("deceased")
|
||||||
|
.where("deceased.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
let findData = manyResult.find(
|
||||||
|
(fitem: any) => fitem.id === item.deceasedId
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...findData,
|
||||||
|
...item,
|
||||||
|
deceased: findData,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await GetData(result);
|
||||||
|
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/query", async (req, res) => {
|
||||||
|
let retailType = Number(req.body.retailType);
|
||||||
|
try {
|
||||||
|
let result = await curd({
|
||||||
|
entity: DeceasedRetail,
|
||||||
|
params: {
|
||||||
|
cancelState: 0,
|
||||||
|
retailType,
|
||||||
|
...req.body,
|
||||||
|
},
|
||||||
|
req,
|
||||||
|
}).queryList();
|
||||||
|
|
||||||
|
if (retailType === 1) {
|
||||||
|
const ids = Array.from(
|
||||||
|
new Set(result.list.map((item) => Number(item.deceasedId)))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ids.length) {
|
||||||
|
const manyResult = await getConnection()
|
||||||
|
.getRepository(Deceased)
|
||||||
|
.createQueryBuilder("deceased")
|
||||||
|
.where("deceased.id IN (:...ids)", {
|
||||||
|
ids,
|
||||||
|
})
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
result.list = result.list.map((item: any) => {
|
||||||
|
let findData = manyResult.find(
|
||||||
|
(fitem: any) => fitem.id === item.deceasedId
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...findData,
|
||||||
|
...item,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await GetData(result);
|
||||||
|
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
70
backEnd/src/router/role/role.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import pagination from "../../lib/pagination/pagination";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { Role } from "../../entity/Role";
|
||||||
|
import curd from "@/lib/curd/curd";
|
||||||
|
|
||||||
|
let router = express.Router();
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
let data = await pagination(Role, req);
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/add", async (req, res) => {
|
||||||
|
let body = req.body;
|
||||||
|
let roleRep = getConnection().manager.getRepository(Role);
|
||||||
|
let findRole = await roleRep.findOne({ where: { name: body.name } });
|
||||||
|
if (findRole) return res.send({ code: 500, msg: "角色名已存在!" });
|
||||||
|
|
||||||
|
await curd({ entity: Role, req }).add();
|
||||||
|
|
||||||
|
return res.send({ code: 200, msg: "角色添加成功!" });
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/query", async (req, res) => {
|
||||||
|
let data = await curd({ entity: Role, req }).queryList();
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/delete", async (req, res) => {
|
||||||
|
let roleRep = getConnection().manager.getRepository(Role);
|
||||||
|
let { id } = req.query;
|
||||||
|
let findMnue = await roleRep.find({ where: { id } });
|
||||||
|
|
||||||
|
if (!findMnue)
|
||||||
|
return res.send({ code: 500, msg: "删除的角色不存在,请检查!" });
|
||||||
|
|
||||||
|
await roleRep.remove(findMnue);
|
||||||
|
return res.send({ code: 200, msg: "删除成功!" });
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/update", async (req, res, next) => {
|
||||||
|
if (!req.body.id)
|
||||||
|
return res.send({ code: 502, msg: "未传入角色ID,请检查数据!" });
|
||||||
|
|
||||||
|
const bodyData = req.body;
|
||||||
|
|
||||||
|
const roleRep = getConnection().manager.getRepository(Role);
|
||||||
|
let findRole = await roleRep.findOne({ where: { id: bodyData.id } });
|
||||||
|
|
||||||
|
findRole = { ...findRole, ...bodyData };
|
||||||
|
findRole.updateDate = new Date();
|
||||||
|
|
||||||
|
await roleRep.save(findRole);
|
||||||
|
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
msg: "角色修改成功!",
|
||||||
|
data: findRole,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
155
backEnd/src/router/serviceList/serviceCategory.ts
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import ServiceCategory from "../../entity/ServiceCategory";
|
||||||
|
import curd from "@/lib/curd/curd";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
req.body.pageSize = "1000";
|
||||||
|
req.query.pageSize = "1000";
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (req.query.all) {
|
||||||
|
req.body.pageSize = "1000";
|
||||||
|
req.query.pageSize = "1000";
|
||||||
|
const result = await curd({ entity: ServiceCategory, req }).queryList();
|
||||||
|
return res.send({ code: 200, data: result });
|
||||||
|
}
|
||||||
|
// 查询数据库中的所有分类数据
|
||||||
|
const result = await curd({ entity: ServiceCategory, req }).queryList();
|
||||||
|
// 将数据转换为树形结构
|
||||||
|
const buildTree = (items, parentId = 0) => {
|
||||||
|
return items
|
||||||
|
.filter((item) => item.parentId === parentId)
|
||||||
|
.map((item) => ({
|
||||||
|
...item,
|
||||||
|
children: buildTree(items, item.id), // 递归构建子节点
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const treeData = buildTree(result.list);
|
||||||
|
|
||||||
|
result.list = treeData;
|
||||||
|
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/query", async (req, res) => {
|
||||||
|
try {
|
||||||
|
// 查询数据库中的所有分类数据
|
||||||
|
const result = await curd({ entity: ServiceCategory, req }).queryList();
|
||||||
|
|
||||||
|
// 将数据转换为树形结构
|
||||||
|
// const buildTree = (items, parentId = 0) => {
|
||||||
|
// return items
|
||||||
|
// .filter((item) => item.parentId === parentId)
|
||||||
|
// .map((item) => ({
|
||||||
|
// ...item,
|
||||||
|
// children: buildTree(items, item.id), // 递归构建子节点
|
||||||
|
// }));
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const treeData = buildTree(result.list);
|
||||||
|
|
||||||
|
// result.list = treeData;
|
||||||
|
|
||||||
|
res.send({ code: 200, data: result });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加商品分类
|
||||||
|
router.post("/add", async (req, res) => {
|
||||||
|
const { name } = req.body;
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
return res.send({ code: 400, msg: "商品分类名称不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const categoryRepository = connection.getRepository(ServiceCategory);
|
||||||
|
|
||||||
|
// 校验是否已存在相同名称的商品分类
|
||||||
|
const existingCategory = await categoryRepository.findOne({
|
||||||
|
where: { name },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingCategory) {
|
||||||
|
return res.send({ code: 400, msg: "商品分类名称已存在,请勿重复添加!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
let newCategory = new ServiceCategory();
|
||||||
|
newCategory = {
|
||||||
|
...newCategory,
|
||||||
|
...req.body,
|
||||||
|
};
|
||||||
|
|
||||||
|
await categoryRepository.save(newCategory);
|
||||||
|
res.send({ code: 200, msg: "商品分类添加成功", data: newCategory });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新商品分类
|
||||||
|
router.post("/update", async (req, res) => {
|
||||||
|
const { id } = req.body;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "商品分类ID不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const categoryRepository = connection.getRepository(ServiceCategory);
|
||||||
|
|
||||||
|
// 查找商品分类
|
||||||
|
let category = await categoryRepository.findOne(Number(id));
|
||||||
|
if (!category) {
|
||||||
|
return res.send({ code: 400, msg: "商品分类不存在!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新字段
|
||||||
|
category = {
|
||||||
|
...category,
|
||||||
|
...req.body,
|
||||||
|
};
|
||||||
|
|
||||||
|
await categoryRepository.save(category);
|
||||||
|
res.send({ code: 200, msg: "商品分类更新成功", data: category });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 删除商品分类
|
||||||
|
router.get("/delete", async (req, res) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "商品分类ID不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const categoryRepository = connection.getRepository(ServiceCategory);
|
||||||
|
|
||||||
|
const category = await categoryRepository.findOne(Number(id));
|
||||||
|
if (!category) {
|
||||||
|
return res.send({ code: 400, msg: "商品分类不存在!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
await categoryRepository.remove(category);
|
||||||
|
res.send({ code: 200, msg: "商品分类删除成功" });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
112
backEnd/src/router/serviceList/serviceItem.ts
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import ServiceItem from "../../entity/ServiceItem";
|
||||||
|
import curd from "@/lib/curd/curd";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// 查询服务项目列表(支持分页)
|
||||||
|
// router.get("/list", async (req, res) => {
|
||||||
|
// try {
|
||||||
|
// const result = await curd({ entity: ServiceItem, req }).queryList();
|
||||||
|
// res.send({ code: 200, data: result });
|
||||||
|
// } catch (err) {
|
||||||
|
// res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
if (req.query.all) {
|
||||||
|
req.body.pageSize = "1000";
|
||||||
|
req.query.pageSize = "1000";
|
||||||
|
}
|
||||||
|
let data = await curd({ entity: ServiceItem, req }).queryList();
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/query", async (req, res) => {
|
||||||
|
let data = await curd({ entity: ServiceItem, req }).queryList();
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加服务项目
|
||||||
|
router.post("/add", async (req, res) => {
|
||||||
|
const { name } = req.body;
|
||||||
|
if (!name) {
|
||||||
|
return res.send({ code: 400, msg: "服务项目名称不能为空!" });
|
||||||
|
}
|
||||||
|
const connection = getConnection();
|
||||||
|
const itemRepository = connection.getRepository(ServiceItem);
|
||||||
|
if (await itemRepository.findOne({ name })) {
|
||||||
|
return res.send({ code: 400, msg: "服务项目名称已存在!" });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const newDeceased = await curd({ entity: ServiceItem, req }).add();
|
||||||
|
res.send({ code: 200, msg: "服务项目添加成功", data: newDeceased });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新服务项目
|
||||||
|
router.post("/update", async (req, res) => {
|
||||||
|
const { id, name } = req.body;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "服务项目ID不能为空!" });
|
||||||
|
}
|
||||||
|
const connection = getConnection();
|
||||||
|
const itemRepository = connection.getRepository(ServiceItem);
|
||||||
|
try {
|
||||||
|
// 查找服务项目
|
||||||
|
let serviceItem = await itemRepository.findOne({ id });
|
||||||
|
if (!serviceItem) {
|
||||||
|
return res.send({ code: 400, msg: "服务项目不存在!" });
|
||||||
|
}
|
||||||
|
if (serviceItem.id !== id && serviceItem.name === name) {
|
||||||
|
return res.send({ code: 400, msg: "服务项目名称已存在!" });
|
||||||
|
}
|
||||||
|
serviceItem = {
|
||||||
|
...serviceItem,
|
||||||
|
...req.body,
|
||||||
|
parentId: req.body.parentId ?? 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
await itemRepository.save(serviceItem);
|
||||||
|
res.send({ code: 200, msg: "服务项目更新成功", data: serviceItem });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 删除服务项目
|
||||||
|
router.get("/delete", async (req, res) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return res.send({ code: 400, msg: "服务项目ID不能为空!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const connection = getConnection();
|
||||||
|
const itemRepository = connection.getRepository(ServiceItem);
|
||||||
|
|
||||||
|
const item = await itemRepository.findOne(Number(id));
|
||||||
|
if (!item) {
|
||||||
|
return res.send({ code: 400, msg: "服务项目不存在!" });
|
||||||
|
}
|
||||||
|
|
||||||
|
await itemRepository.remove(item);
|
||||||
|
res.send({ code: 200, msg: "服务项目删除成功" });
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).send({ code: 500, msg: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
121
backEnd/src/router/stats/controller/dayIncome.ts
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// controllers/paymentStats.ts
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
import { getRepository } from "typeorm";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import CheckoutPaymentRecords from "@/entity/CheckoutPayment";
|
||||||
|
import PaymentRecord from "@/entity/Payment";
|
||||||
|
import DeceasedRetail from "@/entity/DeceasedRetail";
|
||||||
|
import parseRangDate, { handleError } from "@/util/globalMethods";
|
||||||
|
|
||||||
|
// 类型定义
|
||||||
|
type PaymentStats = {
|
||||||
|
cashAmount: number;
|
||||||
|
unionPayAmount: number;
|
||||||
|
cardAmount: number;
|
||||||
|
publicTransferAmount: number;
|
||||||
|
workshopPayment: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StatsResponse = {
|
||||||
|
retail: PaymentStats; // 零售单统计(来自PaymentRecord)
|
||||||
|
service: PaymentStats; // 服务单统计(来自CheckoutPaymentRecords)
|
||||||
|
total: PaymentStats; // 合并统计
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPaymentStats = async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
// 参数处理
|
||||||
|
const { startDate, endDate } = parseRangDate(req);
|
||||||
|
|
||||||
|
// 并行获取统计结果
|
||||||
|
const [retailStats, serviceStats] = await Promise.all([
|
||||||
|
getRetailStats(startDate, endDate),
|
||||||
|
getServiceStats(startDate, endDate),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 构建响应
|
||||||
|
const response: StatsResponse = {
|
||||||
|
retail: retailStats,
|
||||||
|
service: serviceStats,
|
||||||
|
total: {
|
||||||
|
cashAmount: retailStats.cashAmount + serviceStats.cashAmount,
|
||||||
|
unionPayAmount:
|
||||||
|
retailStats.unionPayAmount + serviceStats.unionPayAmount,
|
||||||
|
cardAmount: retailStats.cardAmount + serviceStats.cardAmount,
|
||||||
|
publicTransferAmount:
|
||||||
|
retailStats.publicTransferAmount + serviceStats.publicTransferAmount,
|
||||||
|
workshopPayment:
|
||||||
|
retailStats.workshopPayment + serviceStats.workshopPayment,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
res.json({ code: 200, data: response });
|
||||||
|
} catch (error) {
|
||||||
|
handleError(res, error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 修改后的获取零售单统计
|
||||||
|
const getRetailStats = async (
|
||||||
|
start: string,
|
||||||
|
end: string
|
||||||
|
): Promise<PaymentStats> => {
|
||||||
|
const result = await getRepository(PaymentRecord)
|
||||||
|
.createQueryBuilder("payment")
|
||||||
|
.select([
|
||||||
|
"SUM(payment.cash_amount) AS cashAmount",
|
||||||
|
"SUM(payment.union_pay_amount) AS unionPayAmount",
|
||||||
|
"SUM(payment.card_amount) AS cardAmount",
|
||||||
|
"SUM(payment.public_transfer_amount) AS publicTransferAmount",
|
||||||
|
"SUM(payment.workshop_payment) AS workshopPayment",
|
||||||
|
])
|
||||||
|
.where("payment.checkout_date BETWEEN :start AND :end", { start, end })
|
||||||
|
.andWhere(
|
||||||
|
`(payment.deceased_retail_id IN (
|
||||||
|
SELECT id
|
||||||
|
FROM deceased_retail
|
||||||
|
WHERE retail_state = 1
|
||||||
|
) OR payment.no_deceased_retail_id IN (
|
||||||
|
SELECT id
|
||||||
|
FROM deceased_retail
|
||||||
|
WHERE retail_state = 1
|
||||||
|
))`
|
||||||
|
)
|
||||||
|
.getRawOne();
|
||||||
|
|
||||||
|
return formatStats(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 修改后的获取服务单统计
|
||||||
|
const getServiceStats = async (
|
||||||
|
start: string,
|
||||||
|
end: string
|
||||||
|
): Promise<PaymentStats> => {
|
||||||
|
const result = await getRepository(CheckoutPaymentRecords)
|
||||||
|
.createQueryBuilder("cpr")
|
||||||
|
.innerJoin(
|
||||||
|
DeceasedRetail,
|
||||||
|
"dr",
|
||||||
|
"dr.id = cpr.checkout_retail_id AND dr.retail_state = 1"
|
||||||
|
)
|
||||||
|
.select([
|
||||||
|
"SUM(cpr.cash_amount) AS cashAmount",
|
||||||
|
"SUM(cpr.union_pay_amount) AS unionPayAmount",
|
||||||
|
"SUM(cpr.card_amount) AS cardAmount",
|
||||||
|
"SUM(cpr.public_transfer_amount) AS publicTransferAmount",
|
||||||
|
"SUM(cpr.workshop_payment) AS workshopPayment",
|
||||||
|
])
|
||||||
|
.where("cpr.checkout_date BETWEEN :start AND :end", { start, end })
|
||||||
|
.getRawOne();
|
||||||
|
|
||||||
|
return formatStats(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 格式化统计结果 */
|
||||||
|
const formatStats = (raw: any): PaymentStats => ({
|
||||||
|
cashAmount: Number(raw?.cashAmount || 0),
|
||||||
|
unionPayAmount: Number(raw?.unionPayAmount || 0),
|
||||||
|
cardAmount: Number(raw?.cardAmount || 0),
|
||||||
|
publicTransferAmount: Number(raw?.publicTransferAmount || 0),
|
||||||
|
workshopPayment: Number(raw?.workshopPayment || 0),
|
||||||
|
});
|
||||||
199
backEnd/src/router/stats/controller/salesDetail.ts
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
import { Request, Response } from "express";
|
||||||
|
import { getRepository } from "typeorm";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import DeceasedRetail from "@/entity/DeceasedRetail";
|
||||||
|
import SeletedServiceList from "@/entity/SeletedServiceList";
|
||||||
|
import Deceased from "@/entity/Deceased";
|
||||||
|
import { handleError } from "@/util/globalMethods";
|
||||||
|
|
||||||
|
interface QueryParams {
|
||||||
|
startDate?: string;
|
||||||
|
endDate?: string;
|
||||||
|
serviceName?: string;
|
||||||
|
deceasedName?: string;
|
||||||
|
pageSize?: number;
|
||||||
|
pageNumber?: number;
|
||||||
|
guide?: string;
|
||||||
|
familyName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SalesDetailItem {
|
||||||
|
id: string;
|
||||||
|
checkoutDate: string;
|
||||||
|
deceasedName: string;
|
||||||
|
gender: string;
|
||||||
|
age: number;
|
||||||
|
idCard: string;
|
||||||
|
contactPerson: string;
|
||||||
|
contactPhone: string;
|
||||||
|
serviceName: string;
|
||||||
|
price: number;
|
||||||
|
quantity: number;
|
||||||
|
amount: number;
|
||||||
|
remark: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getSalesDetails = async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const params = parseQueryParams(
|
||||||
|
req.method === "GET" ? req.query : req.body
|
||||||
|
);
|
||||||
|
const pageSize = Number(params.pageSize) || 10;
|
||||||
|
const pageNumber = Number(params.pageNumber) || 1;
|
||||||
|
|
||||||
|
// 第一步:查询 SeletedServiceList 和 DeceasedRetail
|
||||||
|
const initialQuery = getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("ssl")
|
||||||
|
.innerJoinAndMapOne(
|
||||||
|
"ssl.deceasedRetail",
|
||||||
|
DeceasedRetail,
|
||||||
|
"dr",
|
||||||
|
"FIND_IN_SET(ssl.id, dr.serviceItems) AND dr.retailState = 1 AND dr.cancelState = 0 "
|
||||||
|
);
|
||||||
|
|
||||||
|
if (pageSize !== 999999999) {
|
||||||
|
// 如果还没有连接 Deceased 表,需要确保连接
|
||||||
|
if (
|
||||||
|
(params.deceasedName || params.familyName) &&
|
||||||
|
!initialQuery.expressionMap.joinAttributes.some(
|
||||||
|
(join) => join.alias.name === "d"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
initialQuery.innerJoin(Deceased, "d", "d.id = dr.deceasedId");
|
||||||
|
}
|
||||||
|
if (params.startDate || params.endDate) {
|
||||||
|
initialQuery.andWhere("dr.checkoutDate BETWEEN :start AND :end", {
|
||||||
|
start:
|
||||||
|
params.startDate ||
|
||||||
|
dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
end: params.endDate || dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 服务名称条件
|
||||||
|
if (params.serviceName) {
|
||||||
|
initialQuery.andWhere("ssl.name LIKE :serviceName", {
|
||||||
|
serviceName: `%${params.serviceName}%`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.guide) {
|
||||||
|
initialQuery.andWhere("dr.guide LIKE :guide", {
|
||||||
|
guide: `%${params.guide}%`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逝者姓名条件
|
||||||
|
if (params.deceasedName) {
|
||||||
|
initialQuery.andWhere(
|
||||||
|
"( d.name LIKE :deceasedName OR (dr.deceasedId = 0 AND dr.deceasedName LIKE :deceasedName))",
|
||||||
|
{
|
||||||
|
deceasedName: `%${params.deceasedName}%`,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 逝者家属姓名条件
|
||||||
|
if (params.familyName) {
|
||||||
|
initialQuery.andWhere(
|
||||||
|
"( d.familyName LIKE :familyName OR (dr.deceasedId = 0 AND dr.familyName LIKE :familyName) )",
|
||||||
|
{
|
||||||
|
familyName: `%${params.familyName}%`,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行初步查询
|
||||||
|
const initialResult = await initialQuery
|
||||||
|
.orderBy("dr.checkoutDate", "DESC")
|
||||||
|
.skip((pageNumber - 1) * pageSize)
|
||||||
|
.take(pageSize)
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
// 第二步:根据初步查询结果查询绑定 Deceased
|
||||||
|
|
||||||
|
const deceasedIds = initialResult
|
||||||
|
//@ts-ignore
|
||||||
|
.map((item) => item.deceasedRetail?.deceasedId)
|
||||||
|
.filter((id) => id !== undefined && id !== 0);
|
||||||
|
|
||||||
|
const deceasedMap = new Map();
|
||||||
|
if (deceasedIds.length > 0) {
|
||||||
|
const deceasedList = await getRepository(Deceased)
|
||||||
|
.createQueryBuilder("d")
|
||||||
|
.where("d.id IN (:...ids)", { ids: deceasedIds })
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
deceasedList.forEach((deceased) => {
|
||||||
|
deceasedMap.set(deceased.id, deceased);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并结果
|
||||||
|
const result = initialResult.map((item) => {
|
||||||
|
//@ts-ignore
|
||||||
|
if (item.deceasedRetail?.deceasedId !== 0) {
|
||||||
|
//@ts-ignore
|
||||||
|
item.deceased = deceasedMap.get(item.deceasedRetail.deceasedId) || {};
|
||||||
|
} else {
|
||||||
|
//@ts-ignore
|
||||||
|
item.deceased = { ...item.deceasedRetail };
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取总记录数
|
||||||
|
const total = await initialQuery.getCount();
|
||||||
|
res.json({
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
list: result.map((item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
// @ts-ignore
|
||||||
|
sum: Number(item.price).toFixed(2) * Number(item.quantity),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
pageSize,
|
||||||
|
pageNumber,
|
||||||
|
total,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
handleError(res, error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseQueryParams = (query: any): QueryParams => {
|
||||||
|
const {
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
serviceName,
|
||||||
|
deceasedName,
|
||||||
|
guide,
|
||||||
|
pageSize,
|
||||||
|
pageNumber,
|
||||||
|
familyName,
|
||||||
|
} = query;
|
||||||
|
|
||||||
|
const validateDate = (date: string, field: string) => {
|
||||||
|
if (date && !dayjs(date).isValid()) {
|
||||||
|
throw new Error(`${field}格式错误,请使用YYYY-MM-DD格式`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
validateDate(startDate, "开始日期");
|
||||||
|
validateDate(endDate, "结束日期");
|
||||||
|
|
||||||
|
return {
|
||||||
|
startDate: startDate?.trim(),
|
||||||
|
endDate: endDate?.trim(),
|
||||||
|
serviceName: serviceName?.trim(),
|
||||||
|
deceasedName: deceasedName?.trim(),
|
||||||
|
guide: guide?.trim(),
|
||||||
|
pageSize: pageSize ? parseInt(pageSize) : undefined,
|
||||||
|
pageNumber: pageNumber ? parseInt(pageNumber) : undefined,
|
||||||
|
familyName: familyName,
|
||||||
|
};
|
||||||
|
};
|
||||||
272
backEnd/src/router/stats/controller/serviceStats.ts
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
// controllers/serviceStats.ts
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
import { getRepository, In } from "typeorm";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import DeceasedRetail from "@/entity/DeceasedRetail";
|
||||||
|
import SeletedServiceList from "@/entity/SeletedServiceList";
|
||||||
|
import ServiceItem from "@/entity/ServiceItem";
|
||||||
|
import ServiceCategory from "@/entity/ServiceCategory";
|
||||||
|
import { handleError } from "@/util/globalMethods";
|
||||||
|
|
||||||
|
// 类型定义
|
||||||
|
interface ServiceStatsItem {
|
||||||
|
serviceName: string;
|
||||||
|
price: number;
|
||||||
|
unit: string;
|
||||||
|
quantity: number;
|
||||||
|
subtotal: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CategoryStats {
|
||||||
|
categoryName: string;
|
||||||
|
services: ServiceStatsItem[];
|
||||||
|
totalQuantity: number;
|
||||||
|
totalAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StatsResponse {
|
||||||
|
categories: CategoryStats[];
|
||||||
|
otherCategory: CategoryStats;
|
||||||
|
grandTotalQuantity: number;
|
||||||
|
grandTotalAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface QueryParams {
|
||||||
|
startDate?: string;
|
||||||
|
endDate?: string;
|
||||||
|
serviceName?: string;
|
||||||
|
categoryName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getServiceStats = async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
// 1. 参数解析和验证
|
||||||
|
const params = parseQueryParams(
|
||||||
|
req.method === "GET" ? req.query : req.body
|
||||||
|
);
|
||||||
|
// 2. 查询符合条件的零售单(按结账时间)
|
||||||
|
const retailRecords = await getRepository(DeceasedRetail)
|
||||||
|
.createQueryBuilder("dr")
|
||||||
|
.where("dr.checkoutDate BETWEEN :start AND :end", {
|
||||||
|
start:
|
||||||
|
params.startDate ||
|
||||||
|
dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
end: params.endDate || dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
})
|
||||||
|
.andWhere("dr.retailState = 1 AND dr.cancelState = 0") // 只统计已结账的
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
// 3. 收集所有服务项目ID(从serviceItems字段)
|
||||||
|
const allServiceItemIds = retailRecords
|
||||||
|
.map((record) => {
|
||||||
|
try {
|
||||||
|
return record.serviceItems.split(",").map(Number);
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.flat()
|
||||||
|
.filter((id) => id > 0); // 过滤无效ID
|
||||||
|
|
||||||
|
if (allServiceItemIds.length === 0) {
|
||||||
|
return res.json(emptyResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 查询这些服务项目在SeletedServiceList中的记录
|
||||||
|
const selectedServices = await getRepository(SeletedServiceList)
|
||||||
|
.createQueryBuilder("ssl")
|
||||||
|
.where("ssl.id IN (:...ids)", { ids: allServiceItemIds })
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
// 5. 收集所有不重复的服务名称
|
||||||
|
const serviceNames = Array.from(
|
||||||
|
new Set(selectedServices.map((s) => s.name))
|
||||||
|
);
|
||||||
|
if (serviceNames.length === 0) {
|
||||||
|
return res.json(emptyResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 分步查询分类信息
|
||||||
|
// 第一步:查询ServiceItem获取parentIds
|
||||||
|
const serviceItems = await getRepository(ServiceItem)
|
||||||
|
.createQueryBuilder("si")
|
||||||
|
.select(["si.name", "si.parentId"])
|
||||||
|
.where("si.name IN (:...names)", { names: serviceNames })
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
// 第二步:收集所有parentIds
|
||||||
|
const parentIds = Array.from(
|
||||||
|
new Set(serviceItems.map((item) => item.parentId))
|
||||||
|
);
|
||||||
|
|
||||||
|
// 第三步:批量查询分类名称
|
||||||
|
const categories = await getRepository(ServiceCategory)
|
||||||
|
.createQueryBuilder("sc")
|
||||||
|
.select(["sc.id", "sc.name"])
|
||||||
|
.where({ id: In(parentIds) })
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
// 第四步:构建分类ID到名称的映射
|
||||||
|
const categoryIdToName = new Map<number, string>();
|
||||||
|
categories.forEach((cat) => categoryIdToName.set(cat.id, cat.name));
|
||||||
|
|
||||||
|
// 第五步:构建服务名称到分类的映射
|
||||||
|
const nameToCategoryMap = new Map<string, string>();
|
||||||
|
serviceItems.forEach((item) => {
|
||||||
|
const categoryName = categoryIdToName.get(item.parentId) || "其他服务";
|
||||||
|
nameToCategoryMap.set(item.name, categoryName);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 7. 初始化统计结构
|
||||||
|
const categoryStats = new Map<string, ServiceStatsItem[]>();
|
||||||
|
const otherServices: ServiceStatsItem[] = [];
|
||||||
|
|
||||||
|
// 8. 处理每个服务项的统计
|
||||||
|
const serviceNameToStats = new Map<string, ServiceStatsItem>();
|
||||||
|
|
||||||
|
selectedServices.forEach((service) => {
|
||||||
|
// 应用服务名称过滤条件
|
||||||
|
if (params.serviceName && !service.name.includes(params.serviceName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingItem = serviceNameToStats.get(service.name);
|
||||||
|
if (existingItem) {
|
||||||
|
// 如果已存在同名服务,则合并数量和金额
|
||||||
|
existingItem.quantity += service.quantity;
|
||||||
|
existingItem.subtotal += Number(service.price) * service.quantity;
|
||||||
|
} else {
|
||||||
|
// 否则创建新条目
|
||||||
|
serviceNameToStats.set(service.name, {
|
||||||
|
serviceName: service.name,
|
||||||
|
price: Number(service.price),
|
||||||
|
unit: service.unit,
|
||||||
|
quantity: service.quantity,
|
||||||
|
subtotal: Number(service.price) * service.quantity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// // 9. 将合并后的服务项按分类分组
|
||||||
|
// const categoryStats = new Map<string, ServiceStatsItem[]>();
|
||||||
|
// const otherServices: ServiceStatsItem[] = [];
|
||||||
|
|
||||||
|
serviceNameToStats.forEach((statsItem, serviceName) => {
|
||||||
|
// 获取分类名称,默认为"其他服务"
|
||||||
|
const categoryName = nameToCategoryMap.get(serviceName) || "其他服务";
|
||||||
|
|
||||||
|
// 分类到对应分组
|
||||||
|
if (categoryName === "其他服务") {
|
||||||
|
otherServices.push(statsItem);
|
||||||
|
} else {
|
||||||
|
if (!categoryStats.has(categoryName)) {
|
||||||
|
categoryStats.set(categoryName, []);
|
||||||
|
}
|
||||||
|
categoryStats.get(categoryName)?.push(statsItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 9. 应用分类过滤条件
|
||||||
|
if (params.categoryName) {
|
||||||
|
if (params.categoryName !== "其他服务") {
|
||||||
|
categoryStats.forEach((_, key) => {
|
||||||
|
if (key !== params.categoryName) {
|
||||||
|
categoryStats.delete(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
categoryStats.clear(); // 只保留其他服务
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10. 构建最终响应
|
||||||
|
const response = buildFinalResponse(categoryStats, otherServices);
|
||||||
|
res.json({ code: 200, data: response });
|
||||||
|
} catch (error) {
|
||||||
|
handleError(res, error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 辅助函数
|
||||||
|
const emptyResponse = (): StatsResponse => ({
|
||||||
|
categories: [],
|
||||||
|
otherCategory: {
|
||||||
|
categoryName: "其他服务",
|
||||||
|
services: [],
|
||||||
|
totalQuantity: 0,
|
||||||
|
totalAmount: 0,
|
||||||
|
},
|
||||||
|
grandTotalQuantity: 0,
|
||||||
|
grandTotalAmount: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const buildFinalResponse = (
|
||||||
|
categoryMap: Map<string, ServiceStatsItem[]>,
|
||||||
|
otherItems: ServiceStatsItem[]
|
||||||
|
): StatsResponse => {
|
||||||
|
const categories: CategoryStats[] = [];
|
||||||
|
let grandTotalQuantity = 0;
|
||||||
|
let grandTotalAmount = 0;
|
||||||
|
|
||||||
|
// 处理分类数据
|
||||||
|
categoryMap.forEach((items, categoryName) => {
|
||||||
|
const totalQuantity = items.reduce((sum, item) => sum + item.quantity, 0);
|
||||||
|
const totalAmount = items.reduce((sum, item) => sum + item.subtotal, 0);
|
||||||
|
|
||||||
|
categories.push({
|
||||||
|
categoryName,
|
||||||
|
services: items,
|
||||||
|
totalQuantity,
|
||||||
|
totalAmount,
|
||||||
|
});
|
||||||
|
|
||||||
|
grandTotalQuantity += totalQuantity;
|
||||||
|
grandTotalAmount += totalAmount;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 处理其他分类
|
||||||
|
const otherTotalQuantity = otherItems.reduce(
|
||||||
|
(sum, item) => sum + item.quantity,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
const otherTotalAmount = otherItems.reduce(
|
||||||
|
(sum, item) => sum + item.subtotal,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
grandTotalQuantity += otherTotalQuantity;
|
||||||
|
grandTotalAmount += otherTotalAmount;
|
||||||
|
|
||||||
|
return {
|
||||||
|
categories,
|
||||||
|
otherCategory: {
|
||||||
|
categoryName: "其他服务",
|
||||||
|
services: otherItems,
|
||||||
|
totalQuantity: otherTotalQuantity,
|
||||||
|
totalAmount: otherTotalAmount,
|
||||||
|
},
|
||||||
|
grandTotalQuantity,
|
||||||
|
grandTotalAmount,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseQueryParams = (query: any): QueryParams => {
|
||||||
|
const { startDate, endDate, serviceName, categoryName } = query;
|
||||||
|
|
||||||
|
// 日期格式验证
|
||||||
|
const validateDate = (date: string, field: string) => {
|
||||||
|
if (date && !dayjs(date).isValid()) {
|
||||||
|
throw new Error(`${field}格式错误,请使用YYYY-MM-DD格式`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
validateDate(startDate, "开始日期");
|
||||||
|
validateDate(endDate, "结束日期");
|
||||||
|
|
||||||
|
return {
|
||||||
|
startDate: startDate?.trim(),
|
||||||
|
endDate: endDate?.trim(),
|
||||||
|
serviceName: serviceName?.trim(),
|
||||||
|
categoryName: categoryName?.trim(),
|
||||||
|
};
|
||||||
|
};
|
||||||
13
backEnd/src/router/stats/stats.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// controllers/paymentStats.ts
|
||||||
|
import { Router } from "express";
|
||||||
|
import { getPaymentStats } from "./controller/dayIncome";
|
||||||
|
import { getServiceStats } from "./controller/serviceStats";
|
||||||
|
import { getSalesDetails } from "./controller/salesDetail";
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
router.get("/dayIncome", getPaymentStats);
|
||||||
|
router.get("/servicesStats", getServiceStats);
|
||||||
|
router.get("/salesDetails", getSalesDetails);
|
||||||
|
router.post("/salesDetails", getSalesDetails);
|
||||||
|
|
||||||
|
export default router;
|
||||||
102
backEnd/src/router/system-menue/system-menue.ts
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import { SystemMenue } from "../../entity/SystemMenue";
|
||||||
|
import pagination from "../../lib/pagination/pagination";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { filterObjEmptyVal } from "../../util/globalMethods";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
let isAll = req.query.all;
|
||||||
|
req.query.pageSize = "1000";
|
||||||
|
req.body.pageSize = "1000";
|
||||||
|
let data = await pagination(SystemMenue, req);
|
||||||
|
let dataList = [];
|
||||||
|
for (let i = 0; i < data.list.length; i++) {
|
||||||
|
let item = data.list[i];
|
||||||
|
item.children = [];
|
||||||
|
|
||||||
|
for (let j = 0; j < data.list.length; j++) {
|
||||||
|
let tempItem = data.list[j];
|
||||||
|
if (tempItem.parentId === item.id) {
|
||||||
|
item.children.push(tempItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 只添加父级
|
||||||
|
if (!item.parentId || isAll) dataList.push(item);
|
||||||
|
}
|
||||||
|
data.list = dataList;
|
||||||
|
data.total = dataList.length;
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/query", async (req, res) => {
|
||||||
|
let params = req.body;
|
||||||
|
let data = await pagination(SystemMenue, req, filterObjEmptyVal(params));
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/add", async (req, res) => {
|
||||||
|
let menueRep = getConnection().manager.getRepository(SystemMenue);
|
||||||
|
let body = req.body;
|
||||||
|
let findMenue = await menueRep.findOne({ where: { name: body.name } });
|
||||||
|
|
||||||
|
if (findMenue) return res.send({ code: 403, msg: `${body.name}已经存在了` });
|
||||||
|
|
||||||
|
let menueInstance = new SystemMenue();
|
||||||
|
menueInstance = body;
|
||||||
|
menueInstance.createDate = dayjs().format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
await menueRep.save(menueInstance);
|
||||||
|
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
msg: "菜单增加成功!",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/update", async (req, res) => {
|
||||||
|
let menueRep = getConnection().manager.getRepository(SystemMenue);
|
||||||
|
let body = req.body as SystemMenue;
|
||||||
|
|
||||||
|
let filterMenue = await menueRep.findOne({ where: { name: body.name } });
|
||||||
|
if (
|
||||||
|
filterMenue &&
|
||||||
|
filterMenue.id !== body.id &&
|
||||||
|
body.name === filterMenue.name
|
||||||
|
) {
|
||||||
|
return res.send({ code: 500, msg: "菜单名已经存在" });
|
||||||
|
}
|
||||||
|
|
||||||
|
let findMenue = await menueRep.findOne({ where: { id: body.id } });
|
||||||
|
|
||||||
|
findMenue = { ...findMenue, ...body };
|
||||||
|
findMenue.updateDate = dayjs().format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
|
||||||
|
await menueRep.save(findMenue);
|
||||||
|
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
msg: "菜单修改成功!",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/delete", async (req, res) => {
|
||||||
|
let menueRep = getConnection().manager.getRepository(SystemMenue);
|
||||||
|
let { id } = req.query;
|
||||||
|
let findMnue = await menueRep.find({ where: { id } });
|
||||||
|
|
||||||
|
if (!findMnue)
|
||||||
|
return res.send({ code: 500, msg: "删除菜单不存在,请检查!" });
|
||||||
|
|
||||||
|
await menueRep.remove(findMnue);
|
||||||
|
return res.send({ code: 200, msg: "删除成功!" });
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
116
backEnd/src/router/user/user.ts
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import * as express from "express";
|
||||||
|
import { getConnection } from "typeorm";
|
||||||
|
import User from "../../entity/User";
|
||||||
|
import pagination from "../../lib/pagination/pagination";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import curd from "@/lib/curd/curd";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.post("/query", async (req, res) => {
|
||||||
|
const findUsers = await curd({ entity: User, req }).query();
|
||||||
|
if (!findUsers.length) return res.send({ code: 200, data: [] });
|
||||||
|
// 过滤密码
|
||||||
|
findUsers.map((item) => {
|
||||||
|
// @ts-ignore
|
||||||
|
delete item.pwd;
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
list: findUsers,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/list", async (req, res) => {
|
||||||
|
let data = await pagination(User, req);
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/add", async (req, res) => {
|
||||||
|
const connection = getConnection();
|
||||||
|
const bodyData = req.body;
|
||||||
|
|
||||||
|
if (!bodyData.name?.length)
|
||||||
|
return res.send({ code: 502, msg: "用户名是必须的!" });
|
||||||
|
|
||||||
|
const userRep = connection.getRepository(User);
|
||||||
|
const findUser = await userRep.findOne({ name: bodyData.name });
|
||||||
|
|
||||||
|
if (findUser)
|
||||||
|
return res.send({ code: 403, msg: `${bodyData.name}已经存在了!` });
|
||||||
|
|
||||||
|
let userInstance = new User();
|
||||||
|
userInstance = { ...userInstance, ...bodyData };
|
||||||
|
userInstance.createDate = userInstance.createDate || new Date();
|
||||||
|
userInstance.updateDate = userInstance.updateDate || new Date();
|
||||||
|
userInstance.pwd = "E10ADC3949BA59ABBE56E057F20F883E"; // 默认用户密码123456
|
||||||
|
userInstance.birthday = dayjs(userInstance.birthday).format(
|
||||||
|
"YYYY-MM-DD HH:mm:ss"
|
||||||
|
); // 用户默认生日
|
||||||
|
|
||||||
|
await userRep.save(userInstance);
|
||||||
|
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
msg: "用户注册成功!",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/update", async (req, res, next) => {
|
||||||
|
if (!req.body.id)
|
||||||
|
return res.send({ code: 502, msg: "未传入用户ID,请检查数据!" });
|
||||||
|
if (!req.body.pwd) delete req.body.pwd;
|
||||||
|
const findUser = await curd({ entity: User, req }).update();
|
||||||
|
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
msg: "用户修改成功!",
|
||||||
|
data: {
|
||||||
|
userInfo: findUser,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/delete", async (req, res) => {
|
||||||
|
const connection = getConnection();
|
||||||
|
const userRep = connection.getRepository(User);
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
const findUser = await userRep.findOne(id as string);
|
||||||
|
|
||||||
|
if (findUser) {
|
||||||
|
await userRep.remove(findUser);
|
||||||
|
return res.send({
|
||||||
|
code: 200,
|
||||||
|
msg: "用户删除成功!",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return res.send({
|
||||||
|
code: 401,
|
||||||
|
msg: "要删除的用户不存在!",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/resetPwd", async (req, res) => {
|
||||||
|
let userRep = getConnection().getRepository(User);
|
||||||
|
let { id } = req.query;
|
||||||
|
let findUser = await userRep.findOne(id as string);
|
||||||
|
|
||||||
|
if (findUser) {
|
||||||
|
findUser.pwd = "E10ADC3949BA59ABBE56E057F20F883E"; // 默认用户密码123456
|
||||||
|
await userRep.save(findUser);
|
||||||
|
return res.send({ code: 200, msg: "用户密码重置成功!" });
|
||||||
|
} else {
|
||||||
|
return res.send({ code: 500, msg: "用户不存在!" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
81
backEnd/src/util/globalMethods.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import dayjs from "dayjs";
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
|
||||||
|
export function filterObjEmptyVal(obj: { [key: string]: any }) {
|
||||||
|
if (!obj) return {};
|
||||||
|
if (Array.isArray(obj))
|
||||||
|
throw Error("你传入了一个数组,需要的是一个Object对象");
|
||||||
|
|
||||||
|
let emptyObj = {};
|
||||||
|
|
||||||
|
for (let [key, value] of Object.entries(obj)) {
|
||||||
|
if (value || value === 0) emptyObj[key] = value;
|
||||||
|
}
|
||||||
|
return emptyObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNowDateStr() {
|
||||||
|
return dayjs().format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildTree(items, parentId = 0) {
|
||||||
|
return items
|
||||||
|
.filter((item) => item.parentId === parentId)
|
||||||
|
.map((item) => ({
|
||||||
|
...item,
|
||||||
|
children: buildTree(items, item.id),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPaginationParams(req: Request): {
|
||||||
|
pageSize: number;
|
||||||
|
pageNumber: number;
|
||||||
|
} {
|
||||||
|
const { pageSize = 10, pageNumber = 1 } =
|
||||||
|
req.method === "GET" ? req.query : req.body;
|
||||||
|
|
||||||
|
return {
|
||||||
|
pageSize: Math.max(1, parseInt(pageSize as string, 10)),
|
||||||
|
pageNumber: Math.max(1, parseInt(pageNumber as string, 10)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 统一错误处理 */
|
||||||
|
export function handleError(res: Response, error: any) {
|
||||||
|
const message = error instanceof Error ? error.message : "未知错误";
|
||||||
|
res.status(500).json({
|
||||||
|
code: 500,
|
||||||
|
msg: message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理日期参数 */
|
||||||
|
export default function parseRangDate(req: Request) {
|
||||||
|
let { startDate: reqStart, endDate: reqEnd } =
|
||||||
|
req.method === "GET" ? req.query : req.body;
|
||||||
|
const dateFormat = "YYYY-MM-DD HH:mm:ss";
|
||||||
|
|
||||||
|
if (!reqStart && !reqEnd) return {};
|
||||||
|
|
||||||
|
// 验证必填参数
|
||||||
|
if (!reqStart) reqStart = dayjs().startOf("day").toDate();
|
||||||
|
|
||||||
|
// 处理起始日期
|
||||||
|
const start = dayjs(reqStart as string, dateFormat);
|
||||||
|
if (!start.isValid()) throw new Error("起始日期格式错误");
|
||||||
|
|
||||||
|
// 处理结束日期
|
||||||
|
let end = start;
|
||||||
|
if (reqEnd) {
|
||||||
|
end = dayjs(reqEnd as string, dateFormat);
|
||||||
|
if (!end.isValid()) throw new Error("结束日期格式错误");
|
||||||
|
if (end.isBefore(start)) throw new Error("结束日期不能早于起始日期");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成时间范围
|
||||||
|
|
||||||
|
return {
|
||||||
|
startDate: start.format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
endDate: (reqEnd ? end : dayjs()).format("YYYY-MM-DD HH:mm:ss"),
|
||||||
|
};
|
||||||
|
}
|
||||||
27
backEnd/tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["es5", "es6", "ES2022"],
|
||||||
|
"paths": {
|
||||||
|
"router/*": ["./src/router/*"],
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
},
|
||||||
|
"baseUrl": "./",
|
||||||
|
"declaration": true, // 是否生成.d.ts文件
|
||||||
|
"declarationDir": "./types", // .d.ts文件输出路径
|
||||||
|
"target": "ES5", // 编译目标
|
||||||
|
"module": "CommonJS",
|
||||||
|
// "strict": true,
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"outDir": "./build",
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true, // 用于指定是否启用实验性的装饰器特性
|
||||||
|
"sourceMap": false,
|
||||||
|
// "resolveJsonModule": true,
|
||||||
|
"allowSyntheticDefaultImports": true, // 用于允许从没有默认导出的模块中默认导入
|
||||||
|
"esModuleInterop": true, //是否允许export=导出,import from导入
|
||||||
|
},
|
||||||
|
// "ts-node": {
|
||||||
|
// "esm": true
|
||||||
|
// },
|
||||||
|
"include": ["src/**/*", "index.ts"]
|
||||||
|
}
|
||||||
1
backEnd/types/index.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import "./src/util/dotenvConfig";
|
||||||
5
backEnd/types/src/abstrClass/baseEntity.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export declare abstract class BaseEntity {
|
||||||
|
id: number;
|
||||||
|
createDate: string;
|
||||||
|
updateDate: string;
|
||||||
|
}
|
||||||
6
backEnd/types/src/entity/Role.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { BaseEntity } from "../abstrClass/BaseEntity";
|
||||||
|
export declare class Role extends BaseEntity {
|
||||||
|
values: string;
|
||||||
|
roleState: number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
10
backEnd/types/src/entity/SystemMenu.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export declare class SystemMenu {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
createDate: string;
|
||||||
|
updateDate: string;
|
||||||
|
path: string;
|
||||||
|
parentId: number;
|
||||||
|
icon: string;
|
||||||
|
show: boolean;
|
||||||
|
}
|
||||||
18
backEnd/types/src/entity/User.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
export declare class User {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
phone: string;
|
||||||
|
sex: string;
|
||||||
|
pwd: string;
|
||||||
|
createDate: string;
|
||||||
|
updateDate: string;
|
||||||
|
userState: number;
|
||||||
|
role: string;
|
||||||
|
birthday: string;
|
||||||
|
age: string;
|
||||||
|
province: string;
|
||||||
|
city: string;
|
||||||
|
area: string;
|
||||||
|
address: string;
|
||||||
|
}
|
||||||
|
export default User;
|
||||||
30
backEnd/types/src/lib/curd/curd.d.ts
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { Request } from "express";
|
||||||
|
interface CurdOptions {
|
||||||
|
entity: any;
|
||||||
|
req: Request;
|
||||||
|
params: {
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
declare class Curd {
|
||||||
|
private entity;
|
||||||
|
private req;
|
||||||
|
private queryParams;
|
||||||
|
private repositrory;
|
||||||
|
constructor(options: CurdOptions);
|
||||||
|
add(): Promise<{
|
||||||
|
code: number;
|
||||||
|
data: any;
|
||||||
|
}>;
|
||||||
|
delete(): Promise<{
|
||||||
|
code: number;
|
||||||
|
msg: string;
|
||||||
|
}>;
|
||||||
|
update(): Promise<{
|
||||||
|
code: number;
|
||||||
|
data: any;
|
||||||
|
}>;
|
||||||
|
query(): Promise<unknown[]>;
|
||||||
|
}
|
||||||
|
export default function (options: CurdOptions): Curd;
|
||||||
|
export {};
|
||||||
6
backEnd/types/src/lib/menueToTree.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { SystemMenu } from "../../src/entity/SystemMenu";
|
||||||
|
interface routerTree extends SystemMenu {
|
||||||
|
children?: SystemMenu[];
|
||||||
|
}
|
||||||
|
export default function menueToTree(data: SystemMenu[]): routerTree[];
|
||||||
|
export {};
|
||||||
17
backEnd/types/src/lib/pagination/pagination.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Request } from "express";
|
||||||
|
interface paginationType {
|
||||||
|
list: any[];
|
||||||
|
total: number;
|
||||||
|
pageSize: number;
|
||||||
|
pageNumber: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param entite 传入实体类以供查询
|
||||||
|
* @param req express的Request请求体
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function getPagination(entite: any, req: Request, queryParams?: {
|
||||||
|
[key: string]: any;
|
||||||
|
}): Promise<paginationType>;
|
||||||
|
export {};
|
||||||
2
backEnd/types/src/router/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
declare let router: import("express-serve-static-core").Router;
|
||||||
|
export default router;
|
||||||
2
backEnd/types/src/router/login/login.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
declare const router: import("express-serve-static-core").Router;
|
||||||
|
export default router;
|
||||||
2
backEnd/types/src/router/role/role.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
declare let router: import("express-serve-static-core").Router;
|
||||||
|
export default router;
|
||||||
2
backEnd/types/src/router/system-menue/system-menue.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
declare const router: import("express-serve-static-core").Router;
|
||||||
|
export default router;
|
||||||
2
backEnd/types/src/router/user/user.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
declare const router: import("express-serve-static-core").Router;
|
||||||
|
export default router;
|
||||||
5
backEnd/types/src/util/dotenvConfig.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
declare const _default: {
|
||||||
|
development: boolean;
|
||||||
|
production: boolean;
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
2
backEnd/types/src/util/globalMethods.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export declare function filterObjEmptyVal(obj: { [key: string]: any }): {};
|
||||||
|
export declare function getNowDateStr(): string;
|
||||||
22
backEnd/webpack.config.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import path from "path";
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: "./index.ts",
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.ts$/,
|
||||||
|
use: "ts-loader",
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: [".ts", ".js"],
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
filename: "index.js",
|
||||||
|
path: path.resolve(__dirname, "dist"),
|
||||||
|
},
|
||||||
|
target: "node",
|
||||||
|
};
|
||||||
1
frontEnd/.env.development
Normal file
@@ -0,0 +1 @@
|
|||||||
|
VITE_API_BASE_URL = "http://localhost:8101"
|
||||||
1
frontEnd/.env.production
Normal file
@@ -0,0 +1 @@
|
|||||||
|
VITE_API_BASE_URL = "http://106.52.204.157/api"
|
||||||
25
frontEnd/.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
.vscode
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
16
frontEnd/README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Vue 3 + TypeScript + Vite
|
||||||
|
|
||||||
|
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
|
||||||
|
|
||||||
|
## Type Support For `.vue` Imports in TS
|
||||||
|
|
||||||
|
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can enable Volar's Take Over mode by following these steps:
|
||||||
|
|
||||||
|
1. Run `Extensions: Show Built-in Extensions` from VS Code's command palette, look for `TypeScript and JavaScript Language Features`, then right click and select `Disable (Workspace)`. By default, Take Over mode will enable itself if the default TypeScript extension is disabled.
|
||||||
|
2. Reload the VS Code window by running `Developer: Reload Window` from the command palette.
|
||||||
|
|
||||||
|
You can learn more about Take Over mode [here](https://github.com/johnsoncodehk/volar/discussions/471).
|
||||||
17
frontEnd/index.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="./index.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>德孝善延伸服务系统</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- <script src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_29405_22.fc87eeefd2303d03e310328c39223ebb.js"></script> -->
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
4232
frontEnd/package-lock.json
generated
Normal file
39
frontEnd/package.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"name": "basesystemforvue3",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@element-plus/icons-vue": "^2.0.10",
|
||||||
|
"axios": "^1.6.0",
|
||||||
|
"dayjs": "^1.11.5",
|
||||||
|
"echarts": "^5.4.3",
|
||||||
|
"element-china-area-data": "^6.1.0",
|
||||||
|
"element-plus": "^2.8.7",
|
||||||
|
"exceljs": "^4.4.0",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
|
"html2canvas": "^1.4.1",
|
||||||
|
"js-md5": "^0.8.3",
|
||||||
|
"pinia": "^2.0.22",
|
||||||
|
"print-js": "^1.6.0",
|
||||||
|
"vue": "^3.2.37",
|
||||||
|
"vue-json-excel3": "^1.0.29",
|
||||||
|
"vue-router": "^4.1.5",
|
||||||
|
"vue3-print-nb": "^0.1.4",
|
||||||
|
"xlsx": "^0.20.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/file-saver": "^2.0.7",
|
||||||
|
"@types/node": "^18.8.0",
|
||||||
|
"@vitejs/plugin-vue": "^3.1.0",
|
||||||
|
"sass": "^1.79.3",
|
||||||
|
"typescript": "^4.6.4",
|
||||||
|
"vite": "^3.2.11",
|
||||||
|
"vue-tsc": "^0.40.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
frontEnd/public/assets/icon/作废.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747273996941" class="icon" viewBox="0 0 1092 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20912" xmlns:xlink="http://www.w3.org/1999/xlink" width="213.28125" height="200"><path d="M443.733333 955.733333H136.533333c-40.96 0-68.266667-27.306667-68.266666-68.266666V136.533333c0-40.96 27.306667-68.266667 68.266666-68.266666h614.4c40.96 0 68.266667 27.306667 68.266667 68.266666v170.666667c0 20.48 13.653333 34.133333 34.133333 34.133333s34.133333-13.653333 34.133334-34.133333V136.533333c0-75.093333-61.44-136.533333-136.533334-136.533333H136.533333C61.44 0 0 61.44 0 136.533333v750.933334c0 75.093333 61.44 136.533333 136.533333 136.533333h307.2c20.48 0 34.133333-13.653333 34.133334-34.133333s-13.653333-34.133333-34.133334-34.133334z" fill="#777777" p-id="20913"></path><path d="M682.666667 307.2c0-20.48-13.653333-34.133333-34.133334-34.133333h-409.6c-20.48 0-34.133333 13.653333-34.133333 34.133333s13.653333 34.133333 34.133333 34.133333h409.6c20.48 0 34.133333-13.653333 34.133334-34.133333zM238.933333 477.866667c-20.48 0-34.133333 13.653333-34.133333 34.133333s13.653333 34.133333 34.133333 34.133333h204.8c20.48 0 34.133333-13.653333 34.133334-34.133333S464.213333 477.866667 443.733333 477.866667h-204.8zM785.066667 409.6C614.4 409.6 477.866667 546.133333 477.866667 716.8S614.4 1024 785.066667 1024s307.2-136.533333 307.2-307.2S955.733333 409.6 785.066667 409.6z m0 546.133333C655.36 955.733333 546.133333 846.506667 546.133333 716.8S655.36 477.866667 785.066667 477.866667 1024 587.093333 1024 716.8 914.773333 955.733333 785.066667 955.733333z" fill="#777777" p-id="20914"></path><path d="M907.946667 600.746667c-13.653333-13.653333-34.133333-13.653333-47.786667 0l-75.093333 75.093333-75.093334-75.093333c-13.653333-13.653333-34.133333-13.653333-47.786666 0s-13.653333 34.133333 0 47.786666l75.093333 75.093334-75.093333 75.093333c-13.653333 13.653333-13.653333 34.133333 0 47.786667 13.653333 13.653333 34.133333 13.653333 47.786666 0l75.093334-75.093334 75.093333 75.093334c13.653333 13.653333 34.133333 13.653333 47.786667 0 13.653333-13.653333 13.653333-34.133333 0-47.786667l-75.093334-75.093333 75.093334-75.093334c13.653333-13.653333 13.653333-34.133333 0-47.786666z" fill="#777777" p-id="20915"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
1
frontEnd/public/assets/icon/打印机.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747273678337" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12063" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M810.6496 341.3504H213.3504a128 128 0 0 0-128 128v256a85.3504 85.3504 0 0 0 85.2992 85.2992h21.3504V768a128 128 0 0 1 128-128h384a128 128 0 0 1 128 128v42.6496h21.3504a85.3504 85.3504 0 0 0 85.2992-85.2992v-256a128 128 0 0 0-128-128zM768 554.6496a64 64 0 1 1 0-128 64 64 0 0 1 0 128z" fill="#A1A5B3" p-id="12064"></path><path d="M704 746.6496c11.776 0 21.3504 9.5744 21.3504 21.3504v106.6496c0 11.776-9.5744 21.3504-21.3504 21.3504h-384a21.3504 21.3504 0 0 1-21.3504-21.3504V768c0-11.776 9.5744-21.3504 21.3504-21.3504h384m0-64h-384c-47.104 0-85.3504 38.2464-85.3504 85.3504v106.6496c0 47.104 38.2464 85.3504 85.3504 85.3504h384c47.104 0 85.3504-38.1952 85.3504-85.3504V768c0-47.104-38.2464-85.3504-85.3504-85.3504z m85.3504-384H234.6496V192a128 128 0 0 1 128-128h298.7008a128 128 0 0 1 128 128v106.6496z" fill="#C2C4CC" p-id="12065"></path><path d="M650.6496 853.3504H373.3504a32 32 0 0 1 0-64h277.2992a32 32 0 1 1 0 64z" fill="#C2C4CC" p-id="12066"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
1
frontEnd/public/assets/icon/日收入.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747275888152" class="icon" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="37586" xmlns:xlink="http://www.w3.org/1999/xlink" width="200.1953125" height="200"><path d="M658.285714 475.428571c10.971429 0 18.285714-7.314286 18.285715-18.285714s-7.314286-18.285714-18.285715-18.285714h-65.828571l58.514286-58.514286c7.314286-7.314286 7.314286-18.285714 0-25.6-7.314286-7.314286-18.285714-7.314286-25.6 0L541.257143 438.857143h-21.942857l-84.114286-84.114286c-7.314286-7.314286-18.285714-7.314286-25.6 0-7.314286 7.314286-7.314286 18.285714 0 25.6l58.514286 58.514286H402.285714c-10.971429 0-18.285714 7.314286-18.285714 18.285714s7.314286 18.285714 18.285714 18.285714h109.714286v73.142858h-109.714286c-10.971429 0-18.285714 7.314286-18.285714 18.285714s7.314286 18.285714 18.285714 18.285714h109.714286v91.428572c0 10.971429 7.314286 18.285714 18.285714 18.285714s18.285714-7.314286 18.285715-18.285714V585.142857h109.714285c10.971429 0 18.285714-7.314286 18.285715-18.285714s-7.314286-18.285714-18.285715-18.285714h-109.714285v-73.142858h109.714285z" p-id="37587"></path><path d="M983.771429 548.571429h-73.142858V219.428571c0-40.228571-32.914286-73.142857-73.142857-73.142857H223.085714c-40.228571 0-73.142857 32.914286-73.142857 73.142857v329.142858h-73.142857c-40.228571 0-51.2 25.6-21.942857 54.857142l435.2 398.628572c14.628571 14.628571 32.914286 21.942857 51.2 21.942857s36.571429-7.314286 51.2-21.942857l424.228571-398.628572c18.285714-29.257143 7.314286-54.857143-32.914285-54.857142zM559.542857 976.457143c-7.314286 7.314286-14.628571 10.971429-21.942857 10.971428s-18.285714-3.657143-21.942857-10.971428L87.771429 585.142857h98.742857V219.428571c0-21.942857 14.628571-36.571429 36.571428-36.571428H841.142857c21.942857 0 36.571429 14.628571 36.571429 36.571428v365.714286h98.742857L559.542857 976.457143z" p-id="37588"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
1
frontEnd/public/assets/icon/服务.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747273925868" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19834" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M899.584 254.976h-1.024c-3.072-0.512-5.632-0.512-8.704-0.512-27.64288 0-50.68288 16.384-60.416 43.008l-50.176 155.648c-8.19712-3.072-16.896-4.608-26.11712-4.608-14.336 0-28.672 3.584-43.00288 11.264l-163.328 87.04c-13.824 7.168-25.6 17.92-35.328 31.23712-9.728-13.31712-22.016-24.064-35.328-31.23712L312.32 459.264c-14.336-7.68-28.672-11.264-43.008-11.264-9.216 0-17.92 1.536-26.112 4.608L193.024 296.96c-9.216-26.624-32.256-43.008-60.416-43.008-3.072 0-5.632 0-8.704 0.512H122.88c-26.624 4.608-55.296 29.696-55.808 74.24v0.512l7.168 193.536c0 29.70112 9.728 60.928 28.672 91.648 10.24 16.384 23.04 30.208 35.328 43.52l0.512 0.512 99.328 95.744c18.432 17.92 36.352 34.304 48.128 53.76l79.36 129.19296c5.632 9.216 15.36 14.84288 25.6 14.84288 5.632 0 11.264-1.536 16.384-4.60288 14.848-9.22112 18.944-27.14112 9.728-41.984L336.384 773.12c-15.36-25.088-35.84-45.056-56.832-65.536l-98.304-95.232c-29.184-29.17888-46.08-64-47.104-94.72l-7.168-193.536c0-3.584 0.512-9.728 5.632-10.752h0.512c0 0.512 0.512 0.512 0.512 1.024l56.32 176.128 3.072 13.824c3.072 20.48 8.192 43.008 37.888 70.656 4.096 5.63712 9.728 9.728 12.8 11.776l57.344 45.568c7.168 6.144 14.336 7.168 19.456 7.168 8.704 0 16.896-4.10112 22.528-11.264 11.264-13.31712 9.728-31.23712-3.584-41.984l-58.88-46.592c-18.432-14.34112-21.504-25.6-20.992-28.67712 1.536-1.536 4.608-2.56 7.68-2.56 4.096 0 9.728 1.536 14.336 4.096l163.328 87.04c20.48 12.288 32.256 45.06112 31.744 70.144l2.048 96.256v0.51712c0.512 6.144 3.072 11.776 7.168 16.384 4.608 5.632 11.264 9.72288 18.432 11.25888l4.608 1.024h1.024l4.608-1.024c7.168-1.536 13.824-5.632 18.432-11.25888 4.10112-4.608 6.66112-10.75712 7.168-16.384v-0.512l2.048-96.256c0-25.08288 11.776-57.856 31.73888-70.144l162.82112-87.04c5.632-2.56 10.752-4.096 14.84288-4.096 3.07712 0 6.144 1.024 7.68 2.56 0 3.072-2.56 13.824-20.992 28.67712l-58.88 46.592c-13.31712 11.264-14.848 28.672-3.584 41.984 6.144 7.16288 14.336 11.264 22.528 11.264 4.60288 0 11.776-1.024 19.456-7.168l57.344-45.568c3.072-2.04288 8.69888-6.13888 12.8-11.776 29.17888-27.64288 34.816-50.176 37.88288-70.656l3.07712-13.824 56.32-175.616c0.512-1.024 0.512-1.536 1.01888-1.536h1.024c4.608 0.512 5.12 6.656 5.12 10.752l-7.16288 193.536c-1.024 30.72-17.92 65.024-46.59712 94.208l-98.304 95.232C718.848 727.04 698.88 747.52 683.008 772.608l-77.99296 132.77184c-9.216 14.848-4.608 32.768 10.24 41.984 5.12 3.07712 10.752 4.608 16.384 4.608 10.24 0 19.96288-5.63712 25.6-14.848L733.696 807.424c11.776-19.456 29.696-35.84 48.128-53.76l98.816-95.232 1.024-1.01888c12.28288-13.31712 25.08288-27.14112 35.32288-43.52C935.424 583.68 945.664 551.936 945.664 522.24l7.16288-193.536V327.68c2.05312-42.496-26.61888-68.096-53.24288-72.704z" p-id="19835"></path><path d="M512.24064 518.656c-5.31968 0-10.22976-1.4592-15.45216-4.58752-9.45152-5.7344-232.07424-142.30528-233.53856-288.99328 0-85.68832 56.13056-155.4432 144.01024-155.4432 29.07648 0 72.43264 38.2976 96.32256 52.62848l7.79264 4.67456 7.84384-4.57728c25.0368-14.60224 67.69664-52.72576 96.49664-52.72576 87.87456 0 144.00512 69.80096 144.00512 155.5968 0 146.42176-222.62272 283.13088-232.09984 288.87552a27.52 27.52 0 0 1-15.38048 4.55168zM408.0128 129.28512c-54.56384 0-83.59936 43.03872-83.59936 95.94368 0 73.06752 96.49664 165.2736 179.12832 222.03392l8.69888 5.97504 8.69888-5.97504c82.6368-56.7552 179.12832-148.96128 179.12832-222.03392 0-52.90496-29.36832-95.94368-84.352-95.94368-25.10848 0-64.72704 40.15616-83.6608 57.28256-5.44768 5.1968-12.29824 7.89504-19.9168 7.89504a30.16704 30.16704 0 0 1-20.42368-7.84896c-18.9696-17.16224-58.5984-57.32864-83.70176-57.32864z" p-id="19836"></path></svg>
|
||||||
|
After Width: | Height: | Size: 3.9 KiB |
1
frontEnd/public/assets/icon/登记.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747275042139" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25426" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M944.014 711.668L798.505 857.177 696.633 959.053h-96.869a30.514 30.514 0 0 1-30.293-30.3v-97.1l101.757-101.755 145.51-145.51a50 50 0 0 1 70.711 0l56.565 56.565a50 50 0 0 1 0 70.715z m-63.639-49.5l-14.142-14.142a20 20 0 0 0-28.285 0l-208.477 208.48v42.547h42.309l208.6-208.6a20 20 0 0 0-0.005-28.283z m-35.047-150.215a30 30 0 0 1-30-30v-337a20 20 0 0 0-20-20h-650a20 20 0 0 0-20 20v734a20 20 0 0 0 20 20h306a30 30 0 0 1 0 60h-336a50 50 0 0 1-50-50v-794a50 50 0 0 1 50-50h710a50 50 0 0 1 50 50v367a30 30 0 0 1-30 30z m-629-145.021a29.979 29.979 0 0 1 29.979-29.979h448.042a29.979 29.979 0 1 1 0 59.957H246.307a29.979 29.979 0 0 1-29.979-29.978z m365.021 175.021H246.307a29.979 29.979 0 0 1-29.979-29.979v-0.042a29.979 29.979 0 0 1 29.979-29.979h335.042a29.979 29.979 0 0 1 29.979 29.979v0.042a29.979 29.979 0 0 1-29.979 29.979z m-335.042 145a29.979 29.979 0 1 1 0-59.957h221.226a29.979 29.979 0 1 1 0 59.957H246.307z" fill="#333333" p-id="25427"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
1
frontEnd/public/assets/icon/结算.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747275059293" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="26485" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M260.125 588.88l546.277 0 0 50.089-546.277 0 0-50.089zM258.793 781.037l546.272 0 1.266 53.712-546.206 0-1.331-53.712zM553.801 392.334l252.6 0 0 50.914-252.6 0 0-50.914zM608.075 195.662l198.326 0 0 51.863-198.326 0 0-51.863zM851.983 992l-662.768 0c-43.677 0-79.163-37.266-79.163-82.977l0-794.046c0-45.712 35.486-82.977 79.163-82.977l662.768 0c43.677 0 79.162 37.266 79.162 82.977l0 793.985c0 45.773-35.55 83.038-79.162 83.038l0 0 0 0 0 0zM178.994 82.215c-8.952 0-16.444 9.398-16.444 20.444l0 818.68c0 11.113 7.555 20.444 16.444 20.444l683.271 0c8.952 0 16.442-9.398 16.442-20.444l0-818.68c0-11.11-7.555-20.444-16.442-20.444l-683.271 0zM473.112 340.084c7.173 12.253 10.857 26.603 10.857 43.044 0 25.141-7.492 46.149-22.474 62.915-15.047 16.758-36.63 26.722-65.007 29.706l0 43.107-36.058 0 0-42.915c-47.169-4.888-76.434-32.314-87.67-82.271l55.8-14.604c5.143 31.426 22.221 47.169 51.298 47.169 13.582 0 23.615-3.366 30.026-10.096 6.412-6.788 9.651-14.853 9.651-24.377 0-9.904-3.239-17.33-9.651-22.347-6.348-5.08-20.632-11.487-42.66-19.297-19.808-6.918-35.362-13.714-46.534-20.505-11.11-6.667-20.188-16.062-27.17-28.184-6.983-12.127-10.412-26.284-10.412-42.282 0-21.074 6.282-40.122 18.666-56.943 12.504-16.887 31.99-27.235 58.719-30.981l0-33.265 36.058 0 0 33.265c40.313 4.827 66.47 27.615 78.405 68.434l-49.837 20.441c-9.712-27.992-24.63-42.024-45.01-42.024-10.157 0-18.347 3.113-24.44 9.397-6.219 6.282-9.332 13.84-9.332 22.727 0 9.076 2.981 15.998 8.952 20.885 5.966 4.824 18.661 10.857 38.214 17.967 21.396 7.81 38.283 15.3 50.407 22.155 12.19 6.982 21.839 16.63 29.202 28.882l0 0 0 0 0 0z" fill="#272636" p-id="26486"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
1
frontEnd/public/assets/icon/结账.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747273710053" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13144" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M221.3 954.9c-24.7 0-47.6-10.3-64.6-29.1C139.5 906.9 130 881 130 853V655.3H71.4c-2.7 0-4.8-2.5-4.8-5.6v-46.5c0-3.1 2.2-5.6 4.8-5.6H130V429.1H71.4c-2.7 0-4.8-2.5-4.8-5.6V377c0-3.1 2.2-5.6 4.8-5.6H130v-194c0-58.9 40.9-106.7 91.2-106.7h639.3c50.3 0 91.2 47.9 91.2 106.7l-1 624V853c0 28.1-9.4 53.9-26.6 72.8-17 18.7-40 29.1-64.6 29.1H221.3zM758.8 873c0 4.7-0.2 9.4-0.6 14l-0.8 9.7h102.2c23.8 0 42.5-19.2 42.5-43.7v-14.9l-1-660.8c0-26.1-18.1-47.3-40.4-47.3H758.8v743z m-578-20c0 25.3 17 43.7 40.4 43.7H711l-0.8-9.7c-0.4-4.7-0.6-9.3-0.6-14V130H221.3c-22.3 0-40.4 21.2-40.4 47.3v194h57.6c2.7 0 4.8 2.5 4.8 5.6v46.5c0 3.1-2.2 5.6-4.8 5.6h-57.6v168.5h57.6c2.7 0 4.8 2.5 4.8 5.6v46.5c0 3.1-2.2 5.6-4.8 5.6h-57.6V853z m0 0" fill="" p-id="13145"></path><path d="M580.9 505c8.2 0 14.8-11.7 14.8-20.4 0-8.6-6.6-20.4-14.8-20.4h-61.2l44.7-84.8c1.1-3.9-3.4-17.1-10.6-21.3-7.1-4.2-18.6-1.5-22.6 6.1l-52.7 100.1H475l-52.7-100.1c-6.6-11.5-16.2-10.3-23.4-6.1-7.1 4.2-11.6 15.4-10.6 21.3l44.6 84.8h-64.7c-8.2 0-14.8 11.7-14.8 20.4 0 8.6 6.6 20.4 14.8 20.4H458v52.1h-89.8c-8.2 0-14.8 11.7-14.8 20.4 0 8.6 6.6 20.4 14.8 20.4H458v63.3c0 8.6 9.9 15.7 18 15.7 8.2 0 18-7 18-15.7v-63.3h86.6c8.2 0 14.8-11.7 14.8-20.4 0-8.6-6.6-20.4-14.8-20.4H494V505h86.9z m0 0" fill="" p-id="13146"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
1
frontEnd/public/assets/icon/统计.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747275431177" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="30181" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M856.71 784.19H167.86v-640a8 8 0 0 0-8-8h-40a8 8 0 0 0-8 8v688c0 4.42 3.2 8 7.14 8h737.71c3.94 0 7.14-3.58 7.14-8v-40c0.01-4.42-3.19-8-7.14-8z" p-id="30182"></path><path d="M280.73 625.25L247 591.12a8 8 0 0 1 0.06-11.31l256.62-253.75a8 8 0 0 1 11.28 0L658.7 469.79a8 8 0 0 0 11.21 0.1l190-183.19a8 8 0 0 1 11.31 0.21l33.32 34.55a8 8 0 0 1-0.21 11.31l-235.2 226.8a8 8 0 0 1-11.21-0.1L514.71 416.34a8 8 0 0 0-11.28 0L292 625.32a8 8 0 0 1-11.27-0.07z" p-id="30183"></path></svg>
|
||||||
|
After Width: | Height: | Size: 809 B |
1
frontEnd/public/assets/icon/销售明细.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747275809833" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="34834" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M721.175273 116.503273a186.181818 186.181818 0 0 1 186.181818 186.181818v418.909091a186.181818 186.181818 0 0 1-186.181818 186.181818h-418.909091a186.181818 186.181818 0 0 1-186.181818-186.181818v-418.909091a186.181818 186.181818 0 0 1 186.181818-186.181818h418.909091z m0 69.818182h-418.909091a116.363636 116.363636 0 0 0-116.130909 108.730181l-0.232728 7.633455v418.909091a116.363636 116.363636 0 0 0 108.683637 116.130909l7.68 0.232727h418.909091a116.363636 116.363636 0 0 0 116.084363-108.730182l0.279273-7.633454v-418.909091a116.363636 116.363636 0 0 0-108.730182-116.130909l-7.633454-0.232727z m-11.357091 430.405818a34.909091 34.909091 0 0 1 0 69.818182h-279.272727a34.909091 34.909091 0 1 1 0-69.818182h279.272727z m-395.636364 0a34.909091 34.909091 0 1 1 0 69.818182 34.909091 34.909091 0 0 1 0-69.818182z m395.636364-139.636364a34.909091 34.909091 0 0 1 0 69.818182h-279.272727a34.909091 34.909091 0 1 1 0-69.818182h279.272727z m-395.636364 0a34.909091 34.909091 0 1 1 0 69.818182 34.909091 34.909091 0 0 1 0-69.818182z m395.636364-139.636364a34.909091 34.909091 0 0 1 0 69.818182h-279.272727a34.909091 34.909091 0 1 1 0-69.818182h279.272727z m-395.636364 0a34.909091 34.909091 0 1 1 0 69.818182 34.909091 34.909091 0 0 1 0-69.818182z" fill="#353B5E" p-id="34835"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
1
frontEnd/public/assets/icon/销售统计.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747275770123" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32916" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M259.584 656.896v58.368c0 29.184 17.408 53.248 38.912 53.248 21.504 0 38.912-24.064 38.912-53.248v-57.856c0-29.184-17.408-53.248-38.912-53.248-21.504-0.512-38.912 23.552-38.912 52.736zM482.816 768c22.016 0 39.424-19.456 39.424-43.008v-207.36c0-23.552-17.92-43.008-39.424-43.008-22.016 0-39.424 19.456-39.424 43.008v207.36c-0.512 23.552 17.408 43.008 39.424 43.008z" p-id="32917"></path><path d="M820.736 81.408h-294.4c-17.92 0-33.28 15.872-33.28 34.304s15.36 34.304 33.28 34.304h294.4c31.232 0 55.296 25.088 55.296 57.344v617.472c0 32.256-24.064 57.344-55.296 57.344H193.536c-31.232 0-55.296-25.088-55.296-57.344v-305.152c0-18.432-15.36-34.304-33.28-34.304s-33.28 15.872-33.28 34.304v305.152c0 69.12 55.296 126.464 121.856 126.464h627.2c66.56 0 121.856-57.344 121.856-126.464V208.384c0-69.12-55.296-126.976-121.856-126.976z" p-id="32918"></path><path d="M719.872 714.752V343.04c0-29.184-17.408-53.248-39.424-53.248-21.504 0-39.424 24.064-39.424 53.248v371.712c0 29.184 17.408 53.248 39.424 53.248 21.504 0 39.424-24.064 39.424-53.248zM136.192 201.728H112.64c-8.704 0-16.384 3.072-23.04 9.216-6.656 6.144-9.728 14.336-9.728 23.04 0 9.216 3.584 17.408 9.728 23.552 6.656 6.144 14.336 9.216 23.04 9.216h43.52v89.088c0 8.704 3.072 16.384 9.216 23.04 6.144 6.656 14.336 9.728 23.04 9.728 8.704 0 16.896-3.584 23.04-9.728 6.144-6.144 9.728-14.336 9.728-23.04V266.752h43.52c8.704 0 16.384-3.072 22.528-9.216 6.144-6.144 9.216-14.336 9.216-23.552 0-8.704-3.072-16.384-9.216-22.528-6.144-6.144-13.824-9.216-22.528-9.216h-23.04l51.2-61.44c6.144-6.656 8.704-14.848 7.68-23.552-1.024-8.704-4.608-15.872-11.264-22.016-6.144-5.12-12.8-7.68-20.48-7.68h-3.584c-8.704 1.024-16.384 5.12-21.504 11.776L188.416 163.84 134.144 98.816c-5.632-6.656-13.312-10.752-22.016-11.776h-3.584c-7.68 0-14.848 2.56-20.48 8.192-6.144 5.632-10.24 13.312-10.752 22.016-1.024 8.704 1.536 16.896 6.656 23.552l52.224 60.928z" p-id="32919"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
1
frontEnd/public/assets/icon/零售.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747273771618" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16143" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M706.56 343.04v81.92h-76.8V343.04H399.36v81.92H317.44V343.04H194.56v537.6h640V343.04h-128zM317.44 266.24v-15.36c0-102.4 87.04-189.44 194.56-189.44s194.56 87.04 194.56 189.44v15.36H870.4c20.48 0 40.96 15.36 40.96 40.96v614.4c0 20.48-15.36 40.96-40.96 40.96H153.6c-20.48 0-40.96-15.36-40.96-40.96V307.2c0-20.48 15.36-40.96 40.96-40.96h163.84z m81.92 0h230.4v-15.36c0-61.44-51.2-112.64-112.64-112.64s-112.64 51.2-112.64 112.64v15.36h-5.12z" p-id="16144"></path></svg>
|
||||||
|
After Width: | Height: | Size: 798 B |
1
frontEnd/public/assets/icon/零售管理.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747275013441" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="23438" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M585.64608 594.3296h-188.416c-16.384 0-28.672 12.288-28.672 28.672v258.048h245.76v-258.048c0-16.384-12.288-28.672-28.672-28.672z m-12.288 40.96v204.8h-163.84v-204.8h163.84z" p-id="23439"></path><path d="M163.75808 573.8496v245.76c0 8.192 8.192 16.384 16.384 20.48h618.496c8.192 0 16.384-8.192 20.48-16.384v-249.856h40.96v245.76c0 32.768-24.576 57.344-57.344 61.44h-618.496c-32.768 0-57.344-24.576-61.44-57.344v-249.856h40.96zM782.25408 123.2896c16.384 0 28.672 8.192 36.864 20.48l4.096 4.096 73.728 167.936-36.864 16.384-73.728-167.936-4.096-4.096h-581.632-4.096l-73.728 176.128-40.96-16.384 73.728-167.936c8.192-16.384 24.576-24.576 40.96-28.672H782.25408z" p-id="23440"></path><path d="M876.46208 270.7456c20.48 40.96 32.768 69.632 36.864 94.208 4.096 32.768-8.192 69.632-40.96 90.112-61.44 36.864-114.688 28.672-155.648-20.48l-4.096-4.096c-20.48 32.768-49.152 49.152-86.016 53.248h-8.192c-36.864 0-69.632-20.48-98.304-57.344l-4.096-8.192-4.096 4.096c-24.576 36.864-53.248 53.248-86.016 57.344h-8.192c-36.864 0-73.728-20.48-114.688-65.536l-8.192-8.192v4.096c-28.672 36.864-61.44 57.344-94.208 61.44h-8.192c-65.536 12.288-126.976-36.864-126.976-86.016 0-16.384 8.192-40.96 20.48-73.728l8.192-20.48c0-4.096 4.096-8.192 4.096-12.288l8.192-8.192 36.864 16.384-12.288 20.48-4.096 16.384-8.192 16.384c-8.192 20.48-12.288 36.864-12.288 45.056 0 20.48 40.96 53.248 77.824 49.152 32.768-4.096 61.44-24.576 86.016-61.44l4.096-8.192 16.384-24.576 20.48 20.48c40.96 53.248 77.824 77.824 106.496 77.824 24.576 0 49.152-20.48 73.728-61.44l4.096-8.192 20.48-36.864 16.384 36.864c28.672 49.152 53.248 73.728 86.016 73.728 28.672 0 53.248-16.384 69.632-57.344l4.096-8.192 16.384-36.864 20.48 36.864c32.768 61.44 69.632 73.728 118.784 40.96 16.384-12.288 24.576-28.672 24.576-49.152 0-12.288-8.192-28.672-20.48-53.248l-8.192-20.48-4.096-8.192 36.864-16.384z" p-id="23441"></path><path d="M143.36 593.18272c12.288 0 20.48-8.192 20.48-20.48s-8.192-20.48-20.48-20.48-20.48 8.192-20.48 20.48 8.192 20.48 20.48 20.48zM839.68 593.18272c12.288 0 20.48-8.192 20.48-20.48s-8.192-20.48-20.48-20.48-20.48 8.192-20.48 20.48 8.192 20.48 20.48 20.48z" p-id="23442"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
1
frontEnd/public/assets/images/Excel.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746776612034" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3346" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M0 0m184.32 0l655.36 0q184.32 0 184.32 184.32l0 655.36q0 184.32-184.32 184.32l-655.36 0q-184.32 0-184.32-184.32l0-655.36q0-184.32 184.32-184.32Z" fill="#FFFFFF" p-id="3347"></path><path d="M266.24 512h276.48v163.84h-276.48z" fill="#2D5B3A" p-id="3348"></path><path d="M542.72 512h276.48v163.84h-276.48zM266.24 348.16h276.48v163.84h-276.48z" fill="#387A47" p-id="3349"></path><path d="M542.72 348.16h276.48v163.84h-276.48z" fill="#4FA16B" p-id="3350"></path><path d="M266.24 675.84h552.96v122.88a40.96 40.96 0 0 1-40.96 40.96h-471.04a40.96 40.96 0 0 1-40.96-40.96v-122.88z" fill="#2D5B3A" p-id="3351"></path><path d="M307.2 184.32h235.52v163.84h-276.48v-122.88a40.96 40.96 0 0 1 40.96-40.96z" fill="#4FA16B" p-id="3352"></path><path d="M81.92 327.68m40.96 0l286.72 0q40.96 0 40.96 40.96l0 286.72q0 40.96-40.96 40.96l-286.72 0q-40.96 0-40.96-40.96l0-286.72q0-40.96 40.96-40.96Z" fill="#357541" p-id="3353"></path><path d="M542.72 184.32h235.52a40.96 40.96 0 0 1 40.96 40.96v122.88h-276.48v-163.84z" fill="#63C187" p-id="3354"></path><path d="M174.17216 410.89024l63.93856 100.05504-64.29696 102.16448h45.7728l44.032-70.77888h1.44384l44.36992 70.77888h48.128l-65.44384-102.16448 66.56-100.05504h-47.43168l-42.60864 72.76544h-1.82272l-42.82368-72.76544z" fill="#FFFFFF" p-id="3355"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
frontEnd/public/assets/images/defaultImg.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
frontEnd/public/assets/images/qinWei.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
frontEnd/public/excelTemple/日收入统计.xlsx
Normal file
BIN
frontEnd/public/excelTemple/销售明细.xlsx
Normal file
BIN
frontEnd/public/index.ico
Normal file
|
After Width: | Height: | Size: 91 KiB |
14
frontEnd/src/App.vue
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<template>
|
||||||
|
<div class="view-content">
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.view-content {
|
||||||
|
min-height: 100vh;
|
||||||
|
min-width: 100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
540
frontEnd/src/assets/css/aliIcon/demo.css
Normal file
@@ -0,0 +1,540 @@
|
|||||||
|
/* Logo 字体 */
|
||||||
|
@font-face {
|
||||||
|
font-family: "iconfont logo";
|
||||||
|
src: url("https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834");
|
||||||
|
src: url("https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix")
|
||||||
|
format("embedded-opentype"),
|
||||||
|
url("https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834")
|
||||||
|
format("woff"),
|
||||||
|
url("https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834")
|
||||||
|
format("truetype"),
|
||||||
|
url("https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont")
|
||||||
|
format("svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-family: "iconfont logo";
|
||||||
|
font-size: 160px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tabs */
|
||||||
|
.nav-tabs {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tabs .nav-more {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
height: 42px;
|
||||||
|
line-height: 42px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabs {
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabs li {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100px;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabs .active {
|
||||||
|
border-bottom-color: #f00;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-container .content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 页面布局 */
|
||||||
|
.main {
|
||||||
|
padding: 30px 100px;
|
||||||
|
width: 960px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main .logo {
|
||||||
|
color: #333;
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
line-height: 1;
|
||||||
|
height: 110px;
|
||||||
|
margin-top: -50px;
|
||||||
|
overflow: hidden;
|
||||||
|
*zoom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main .logo a {
|
||||||
|
font-size: 160px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helps {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helps pre {
|
||||||
|
padding: 20px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border: solid 1px #e7e1cd;
|
||||||
|
background-color: #fffdef;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists {
|
||||||
|
width: 100% !important;
|
||||||
|
overflow: hidden;
|
||||||
|
*zoom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists li {
|
||||||
|
width: 100px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-right: 20px;
|
||||||
|
text-align: center;
|
||||||
|
list-style: none !important;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists li .code-name {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists .icon {
|
||||||
|
display: block;
|
||||||
|
height: 100px;
|
||||||
|
line-height: 100px;
|
||||||
|
font-size: 42px;
|
||||||
|
margin: 10px auto;
|
||||||
|
color: #333;
|
||||||
|
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
|
||||||
|
-moz-transition: font-size 0.25s linear, width 0.25s linear;
|
||||||
|
transition: font-size 0.25s linear, width 0.25s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists .icon:hover {
|
||||||
|
font-size: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists .svg-icon {
|
||||||
|
/* 通过设置 font-size 来改变图标大小 */
|
||||||
|
width: 1em;
|
||||||
|
/* 图标和文字相邻时,垂直对齐 */
|
||||||
|
vertical-align: -0.15em;
|
||||||
|
/* 通过设置 color 来改变 SVG 的颜色/fill */
|
||||||
|
fill: currentColor;
|
||||||
|
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
|
||||||
|
normalize.css 中也包含这行 */
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon_lists li .name,
|
||||||
|
.icon_lists li .code-name {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* markdown 样式 */
|
||||||
|
.markdown {
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown img {
|
||||||
|
vertical-align: middle;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h1 {
|
||||||
|
color: #404040;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 40px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h2,
|
||||||
|
.markdown h3,
|
||||||
|
.markdown h4,
|
||||||
|
.markdown h5,
|
||||||
|
.markdown h6 {
|
||||||
|
color: #404040;
|
||||||
|
margin: 1.6em 0 0.6em 0;
|
||||||
|
font-weight: 500;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h2 {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h4 {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h5 {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h6 {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown hr {
|
||||||
|
height: 1px;
|
||||||
|
border: 0;
|
||||||
|
background: #e9e9e9;
|
||||||
|
margin: 16px 0;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown p {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > p,
|
||||||
|
.markdown > blockquote,
|
||||||
|
.markdown > .highlight,
|
||||||
|
.markdown > ol,
|
||||||
|
.markdown > ul {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown ul > li {
|
||||||
|
list-style: circle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > ul li,
|
||||||
|
.markdown blockquote ul > li {
|
||||||
|
margin-left: 20px;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > ul li p,
|
||||||
|
.markdown > ol li p {
|
||||||
|
margin: 0.6em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown ol > li {
|
||||||
|
list-style: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > ol li,
|
||||||
|
.markdown blockquote ol > li {
|
||||||
|
margin-left: 20px;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown code {
|
||||||
|
margin: 0 3px;
|
||||||
|
padding: 0 5px;
|
||||||
|
background: #eee;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown strong,
|
||||||
|
.markdown b {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0px;
|
||||||
|
empty-cells: show;
|
||||||
|
border: 1px solid #e9e9e9;
|
||||||
|
width: 95%;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > table th {
|
||||||
|
white-space: nowrap;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > table th,
|
||||||
|
.markdown > table td {
|
||||||
|
border: 1px solid #e9e9e9;
|
||||||
|
padding: 8px 16px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > table th {
|
||||||
|
background: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown blockquote {
|
||||||
|
font-size: 90%;
|
||||||
|
color: #999;
|
||||||
|
border-left: 4px solid #e9e9e9;
|
||||||
|
padding-left: 0.8em;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown blockquote p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown .anchor {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown .waiting {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h1:hover .anchor,
|
||||||
|
.markdown h2:hover .anchor,
|
||||||
|
.markdown h3:hover .anchor,
|
||||||
|
.markdown h4:hover .anchor,
|
||||||
|
.markdown h5:hover .anchor,
|
||||||
|
.markdown h6:hover .anchor {
|
||||||
|
opacity: 1;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > br,
|
||||||
|
.markdown > p > br {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
display: block;
|
||||||
|
background: white;
|
||||||
|
padding: 0.5em;
|
||||||
|
color: #333333;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-comment,
|
||||||
|
.hljs-meta {
|
||||||
|
color: #969896;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-string,
|
||||||
|
.hljs-variable,
|
||||||
|
.hljs-template-variable,
|
||||||
|
.hljs-strong,
|
||||||
|
.hljs-emphasis,
|
||||||
|
.hljs-quote {
|
||||||
|
color: #df5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-keyword,
|
||||||
|
.hljs-selector-tag,
|
||||||
|
.hljs-type {
|
||||||
|
color: #a71d5d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-literal,
|
||||||
|
.hljs-symbol,
|
||||||
|
.hljs-bullet,
|
||||||
|
.hljs-attribute {
|
||||||
|
color: #0086b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-section,
|
||||||
|
.hljs-name {
|
||||||
|
color: #63a35c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-tag {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-title,
|
||||||
|
.hljs-attr,
|
||||||
|
.hljs-selector-id,
|
||||||
|
.hljs-selector-class,
|
||||||
|
.hljs-selector-attr,
|
||||||
|
.hljs-selector-pseudo {
|
||||||
|
color: #795da3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-addition {
|
||||||
|
color: #55a532;
|
||||||
|
background-color: #eaffea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-deletion {
|
||||||
|
color: #bd2c00;
|
||||||
|
background-color: #ffecec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-link {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 代码高亮 */
|
||||||
|
/* PrismJS 1.15.0
|
||||||
|
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
|
||||||
|
/**
|
||||||
|
* prism.js default theme for JavaScript, CSS and HTML
|
||||||
|
* Based on dabblet (http://dabblet.com)
|
||||||
|
* @author Lea Verou
|
||||||
|
*/
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: black;
|
||||||
|
background: none;
|
||||||
|
text-shadow: 0 1px white;
|
||||||
|
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::-moz-selection,
|
||||||
|
pre[class*="language-"] ::-moz-selection,
|
||||||
|
code[class*="language-"]::-moz-selection,
|
||||||
|
code[class*="language-"] ::-moz-selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::selection,
|
||||||
|
pre[class*="language-"] ::selection,
|
||||||
|
code[class*="language-"]::selection,
|
||||||
|
code[class*="language-"] ::selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: 0.5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background: #f5f2f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre) > code[class*="language-"] {
|
||||||
|
padding: 0.1em;
|
||||||
|
border-radius: 0.3em;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.namespace {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #905;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.inserted {
|
||||||
|
color: #690;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.handler,
|
||||||
|
.token.entity,
|
||||||
|
.token.url,
|
||||||
|
.language-css .token.string,
|
||||||
|
.style .token.string {
|
||||||
|
color: #9a6e3a;
|
||||||
|
background: hsla(0, 0%, 100%, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.keyword {
|
||||||
|
color: #07a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function,
|
||||||
|
.token.class-name {
|
||||||
|
color: #dd4a68;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important,
|
||||||
|
.token.variable {
|
||||||
|
color: #e90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
832
frontEnd/src/assets/css/aliIcon/demo_index.html
Normal file
@@ -0,0 +1,832 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>iconfont Demo</title>
|
||||||
|
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
|
||||||
|
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
|
||||||
|
<link rel="stylesheet" href="demo.css">
|
||||||
|
<link rel="stylesheet" href="iconfont.css">
|
||||||
|
<script src="iconfont.js"></script>
|
||||||
|
<!-- jQuery -->
|
||||||
|
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
|
||||||
|
<!-- 代码高亮 -->
|
||||||
|
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
|
||||||
|
<style>
|
||||||
|
.main .logo {
|
||||||
|
margin-top: 0;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main .logo a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main .logo .sub-title {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
font-size: 22px;
|
||||||
|
color: #fff;
|
||||||
|
background: linear-gradient(-45deg, #3967FF, #B500FE);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="main">
|
||||||
|
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
|
||||||
|
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
|
||||||
|
|
||||||
|
</a></h1>
|
||||||
|
<div class="nav-tabs">
|
||||||
|
<ul id="tabs" class="dib-box">
|
||||||
|
<li class="dib active"><span>Unicode</span></li>
|
||||||
|
<li class="dib"><span>Font class</span></li>
|
||||||
|
<li class="dib"><span>Symbol</span></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2881943" target="_blank" class="nav-more">查看项目</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="tab-container">
|
||||||
|
<div class="content unicode" style="display: block;">
|
||||||
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">日志下载-下载所有</div>
|
||||||
|
<div class="code-name">&#xe757;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">导航</div>
|
||||||
|
<div class="code-name">&#xe611;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">qq</div>
|
||||||
|
<div class="code-name">&#xe601;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">微信</div>
|
||||||
|
<div class="code-name">&#xe602;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">电话</div>
|
||||||
|
<div class="code-name">&#xe61b;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">地址</div>
|
||||||
|
<div class="code-name">&#xe652;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">姓名</div>
|
||||||
|
<div class="code-name">&#xe635;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">top_联系方式</div>
|
||||||
|
<div class="code-name">&#xe612;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">童装性别</div>
|
||||||
|
<div class="code-name">&#xe614;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">首页</div>
|
||||||
|
<div class="code-name">&#xe68a;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">设置</div>
|
||||||
|
<div class="code-name">&#xe62a;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">账号管理</div>
|
||||||
|
<div class="code-name">&#xe639;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">角色管理</div>
|
||||||
|
<div class="code-name">&#xe640;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">菜单</div>
|
||||||
|
<div class="code-name">&#xe65d;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">菜单</div>
|
||||||
|
<div class="code-name">&#xe609;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">部门</div>
|
||||||
|
<div class="code-name">&#xe686;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">版权</div>
|
||||||
|
<div class="code-name">&#xe66d;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">登陆-box-线</div>
|
||||||
|
<div class="code-name">&#xe89f;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">3.1电话</div>
|
||||||
|
<div class="code-name">&#xe600;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">个人信息</div>
|
||||||
|
<div class="code-name">&#xe641;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">全屏</div>
|
||||||
|
<div class="code-name">&#xe632;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">个人信息</div>
|
||||||
|
<div class="code-name">&#xe603;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">关机</div>
|
||||||
|
<div class="code-name">&#xe689;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">email</div>
|
||||||
|
<div class="code-name">&#xe6b0;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">密码</div>
|
||||||
|
<div class="code-name">&#xe60f;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">验证码</div>
|
||||||
|
<div class="code-name">&#xe619;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">用户名</div>
|
||||||
|
<div class="code-name">&#xe78f;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system"></span>
|
||||||
|
<div class="name">用户登陆统计</div>
|
||||||
|
<div class="code-name">&#xe6ae;</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<div class="article markdown">
|
||||||
|
<h2 id="unicode-">Unicode 引用</h2>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
|
||||||
|
<ul>
|
||||||
|
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
|
||||||
|
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
|
||||||
|
</ul>
|
||||||
|
<blockquote>
|
||||||
|
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Unicode 使用步骤如下:</p>
|
||||||
|
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
|
||||||
|
<pre><code class="language-css"
|
||||||
|
>@font-face {
|
||||||
|
font-family: 'base-system';
|
||||||
|
src: url('iconfont.woff2?t=1713884780448') format('woff2'),
|
||||||
|
url('iconfont.woff?t=1713884780448') format('woff'),
|
||||||
|
url('iconfont.ttf?t=1713884780448') format('truetype');
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||||
|
<pre><code class="language-css"
|
||||||
|
>.base-system {
|
||||||
|
font-family: "base-system" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
|
||||||
|
<pre>
|
||||||
|
<code class="language-html"
|
||||||
|
><span class="base-system">&#x33;</span>
|
||||||
|
</code></pre>
|
||||||
|
<blockquote>
|
||||||
|
<p>"base-system" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content font-class">
|
||||||
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-rizhixiazai-xiazaisuoyou"></span>
|
||||||
|
<div class="name">
|
||||||
|
日志下载-下载所有
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-rizhixiazai-xiazaisuoyou
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-daohang"></span>
|
||||||
|
<div class="name">
|
||||||
|
导航
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-daohang
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-qq"></span>
|
||||||
|
<div class="name">
|
||||||
|
qq
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-qq
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-weixin"></span>
|
||||||
|
<div class="name">
|
||||||
|
微信
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-weixin
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-dianhua"></span>
|
||||||
|
<div class="name">
|
||||||
|
电话
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-dianhua
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-dizhi"></span>
|
||||||
|
<div class="name">
|
||||||
|
地址
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-dizhi
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-xingming"></span>
|
||||||
|
<div class="name">
|
||||||
|
姓名
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-xingming
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-top_lianxifangshi"></span>
|
||||||
|
<div class="name">
|
||||||
|
top_联系方式
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-top_lianxifangshi
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-tongzhuangxingbie"></span>
|
||||||
|
<div class="name">
|
||||||
|
童装性别
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-tongzhuangxingbie
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-home"></span>
|
||||||
|
<div class="name">
|
||||||
|
首页
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-home
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-shezhi"></span>
|
||||||
|
<div class="name">
|
||||||
|
设置
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-shezhi
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-zhanghaoguanli"></span>
|
||||||
|
<div class="name">
|
||||||
|
账号管理
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-zhanghaoguanli
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-navicon-jsgl"></span>
|
||||||
|
<div class="name">
|
||||||
|
角色管理
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-navicon-jsgl
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-caidan"></span>
|
||||||
|
<div class="name">
|
||||||
|
菜单
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-caidan
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-caidan1"></span>
|
||||||
|
<div class="name">
|
||||||
|
菜单
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-caidan1
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-bumen"></span>
|
||||||
|
<div class="name">
|
||||||
|
部门
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-bumen
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-banquan"></span>
|
||||||
|
<div class="name">
|
||||||
|
版权
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-banquan
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-denglu-box-xian"></span>
|
||||||
|
<div class="name">
|
||||||
|
登陆-box-线
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-denglu-box-xian
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-31dianhua"></span>
|
||||||
|
<div class="name">
|
||||||
|
3.1电话
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-31dianhua
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-gerenxinxi"></span>
|
||||||
|
<div class="name">
|
||||||
|
个人信息
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-gerenxinxi
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-quanping"></span>
|
||||||
|
<div class="name">
|
||||||
|
全屏
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-quanping
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-gerenxinxi1"></span>
|
||||||
|
<div class="name">
|
||||||
|
个人信息
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-gerenxinxi1
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-guanji"></span>
|
||||||
|
<div class="name">
|
||||||
|
关机
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-guanji
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-youxiang"></span>
|
||||||
|
<div class="name">
|
||||||
|
email
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-youxiang
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-mima"></span>
|
||||||
|
<div class="name">
|
||||||
|
密码
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-mima
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-yanzhengma"></span>
|
||||||
|
<div class="name">
|
||||||
|
验证码
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-yanzhengma
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-yonghuming"></span>
|
||||||
|
<div class="name">
|
||||||
|
用户名
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-yonghuming
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<span class="icon base-system base-system-yonghudenglutongjigongju"></span>
|
||||||
|
<div class="name">
|
||||||
|
用户登陆统计
|
||||||
|
</div>
|
||||||
|
<div class="code-name">.base-system-yonghudenglutongjigongju
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<div class="article markdown">
|
||||||
|
<h2 id="font-class-">font-class 引用</h2>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
|
||||||
|
<p>与 Unicode 使用方式相比,具有如下特点:</p>
|
||||||
|
<ul>
|
||||||
|
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
|
||||||
|
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
|
||||||
|
</ul>
|
||||||
|
<p>使用步骤如下:</p>
|
||||||
|
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
|
||||||
|
<pre><code class="language-html"><link rel="stylesheet" href="./iconfont.css">
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||||
|
<pre><code class="language-html"><span class="base-system base-system-xxx"></span>
|
||||||
|
</code></pre>
|
||||||
|
<blockquote>
|
||||||
|
<p>"
|
||||||
|
base-system" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content symbol">
|
||||||
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-rizhixiazai-xiazaisuoyou"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">日志下载-下载所有</div>
|
||||||
|
<div class="code-name">#base-system-rizhixiazai-xiazaisuoyou</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-daohang"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">导航</div>
|
||||||
|
<div class="code-name">#base-system-daohang</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-qq"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">qq</div>
|
||||||
|
<div class="code-name">#base-system-qq</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-weixin"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">微信</div>
|
||||||
|
<div class="code-name">#base-system-weixin</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-dianhua"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">电话</div>
|
||||||
|
<div class="code-name">#base-system-dianhua</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-dizhi"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">地址</div>
|
||||||
|
<div class="code-name">#base-system-dizhi</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-xingming"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">姓名</div>
|
||||||
|
<div class="code-name">#base-system-xingming</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-top_lianxifangshi"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">top_联系方式</div>
|
||||||
|
<div class="code-name">#base-system-top_lianxifangshi</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-tongzhuangxingbie"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">童装性别</div>
|
||||||
|
<div class="code-name">#base-system-tongzhuangxingbie</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-home"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">首页</div>
|
||||||
|
<div class="code-name">#base-system-home</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-shezhi"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">设置</div>
|
||||||
|
<div class="code-name">#base-system-shezhi</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-zhanghaoguanli"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">账号管理</div>
|
||||||
|
<div class="code-name">#base-system-zhanghaoguanli</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-navicon-jsgl"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">角色管理</div>
|
||||||
|
<div class="code-name">#base-system-navicon-jsgl</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-caidan"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">菜单</div>
|
||||||
|
<div class="code-name">#base-system-caidan</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-caidan1"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">菜单</div>
|
||||||
|
<div class="code-name">#base-system-caidan1</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-bumen"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">部门</div>
|
||||||
|
<div class="code-name">#base-system-bumen</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-banquan"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">版权</div>
|
||||||
|
<div class="code-name">#base-system-banquan</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-denglu-box-xian"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">登陆-box-线</div>
|
||||||
|
<div class="code-name">#base-system-denglu-box-xian</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-31dianhua"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">3.1电话</div>
|
||||||
|
<div class="code-name">#base-system-31dianhua</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-gerenxinxi"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">个人信息</div>
|
||||||
|
<div class="code-name">#base-system-gerenxinxi</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-quanping"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">全屏</div>
|
||||||
|
<div class="code-name">#base-system-quanping</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-gerenxinxi1"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">个人信息</div>
|
||||||
|
<div class="code-name">#base-system-gerenxinxi1</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-guanji"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">关机</div>
|
||||||
|
<div class="code-name">#base-system-guanji</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-youxiang"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">email</div>
|
||||||
|
<div class="code-name">#base-system-youxiang</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-mima"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">密码</div>
|
||||||
|
<div class="code-name">#base-system-mima</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-yanzhengma"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">验证码</div>
|
||||||
|
<div class="code-name">#base-system-yanzhengma</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-yonghuming"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">用户名</div>
|
||||||
|
<div class="code-name">#base-system-yonghuming</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="dib">
|
||||||
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#base-system-yonghudenglutongjigongju"></use>
|
||||||
|
</svg>
|
||||||
|
<div class="name">用户登陆统计</div>
|
||||||
|
<div class="code-name">#base-system-yonghudenglutongjigongju</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<div class="article markdown">
|
||||||
|
<h2 id="symbol-">Symbol 引用</h2>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
|
||||||
|
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
|
||||||
|
<ul>
|
||||||
|
<li>支持多色图标了,不再受单色限制。</li>
|
||||||
|
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
|
||||||
|
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
|
||||||
|
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
|
||||||
|
</ul>
|
||||||
|
<p>使用步骤如下:</p>
|
||||||
|
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
|
||||||
|
<pre><code class="language-html"><script src="./iconfont.js"></script>
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
|
||||||
|
<pre><code class="language-html"><style>
|
||||||
|
.icon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
vertical-align: -0.15em;
|
||||||
|
fill: currentColor;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</code></pre>
|
||||||
|
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||||
|
<pre><code class="language-html"><svg class="icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-xxx"></use>
|
||||||
|
</svg>
|
||||||
|
</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('.tab-container .content:first').show()
|
||||||
|
|
||||||
|
$('#tabs li').click(function (e) {
|
||||||
|
var tabContent = $('.tab-container .content')
|
||||||
|
var index = $(this).index()
|
||||||
|
|
||||||
|
if ($(this).hasClass('active')) {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
$('#tabs li').removeClass('active')
|
||||||
|
$(this).addClass('active')
|
||||||
|
|
||||||
|
tabContent.hide().eq(index).fadeIn()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
127
frontEnd/src/assets/css/aliIcon/iconfont.css
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "base-system"; /* Project id 2881943 */
|
||||||
|
src: url('iconfont.woff2?t=1713884780448') format('woff2'),
|
||||||
|
url('iconfont.woff?t=1713884780448') format('woff'),
|
||||||
|
url('iconfont.ttf?t=1713884780448') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system {
|
||||||
|
font-family: "base-system" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-rizhixiazai-xiazaisuoyou:before {
|
||||||
|
content: "\e757";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-daohang:before {
|
||||||
|
content: "\e611";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-qq:before {
|
||||||
|
content: "\e601";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-weixin:before {
|
||||||
|
content: "\e602";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-dianhua:before {
|
||||||
|
content: "\e61b";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-dizhi:before {
|
||||||
|
content: "\e652";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-xingming:before {
|
||||||
|
content: "\e635";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-top_lianxifangshi:before {
|
||||||
|
content: "\e612";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-tongzhuangxingbie:before {
|
||||||
|
content: "\e614";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-home:before {
|
||||||
|
content: "\e68a";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-shezhi:before {
|
||||||
|
content: "\e62a";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-zhanghaoguanli:before {
|
||||||
|
content: "\e639";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-navicon-jsgl:before {
|
||||||
|
content: "\e640";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-caidan:before {
|
||||||
|
content: "\e65d";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-caidan1:before {
|
||||||
|
content: "\e609";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-bumen:before {
|
||||||
|
content: "\e686";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-banquan:before {
|
||||||
|
content: "\e66d";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-denglu-box-xian:before {
|
||||||
|
content: "\e89f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-31dianhua:before {
|
||||||
|
content: "\e600";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-gerenxinxi:before {
|
||||||
|
content: "\e641";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-quanping:before {
|
||||||
|
content: "\e632";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-gerenxinxi1:before {
|
||||||
|
content: "\e603";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-guanji:before {
|
||||||
|
content: "\e689";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-youxiang:before {
|
||||||
|
content: "\e6b0";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-mima:before {
|
||||||
|
content: "\e60f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-yanzhengma:before {
|
||||||
|
content: "\e619";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-yonghuming:before {
|
||||||
|
content: "\e78f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-system-yonghudenglutongjigongju:before {
|
||||||
|
content: "\e6ae";
|
||||||
|
}
|
||||||
|
|
||||||
1
frontEnd/src/assets/css/aliIcon/iconfont.js
Normal file
205
frontEnd/src/assets/css/aliIcon/iconfont.json
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
{
|
||||||
|
"id": "2881943",
|
||||||
|
"name": "默认系统",
|
||||||
|
"font_family": "base-system",
|
||||||
|
"css_prefix_text": "base-system-",
|
||||||
|
"description": "通用项目模板图标库",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "21182922",
|
||||||
|
"name": "日志下载-下载所有",
|
||||||
|
"font_class": "rizhixiazai-xiazaisuoyou",
|
||||||
|
"unicode": "e757",
|
||||||
|
"unicode_decimal": 59223
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "4437590",
|
||||||
|
"name": "导航",
|
||||||
|
"font_class": "daohang",
|
||||||
|
"unicode": "e611",
|
||||||
|
"unicode_decimal": 58897
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26701",
|
||||||
|
"name": "qq",
|
||||||
|
"font_class": "qq",
|
||||||
|
"unicode": "e601",
|
||||||
|
"unicode_decimal": 58881
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "77156",
|
||||||
|
"name": "微信",
|
||||||
|
"font_class": "weixin",
|
||||||
|
"unicode": "e602",
|
||||||
|
"unicode_decimal": 58882
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "144688",
|
||||||
|
"name": "电话",
|
||||||
|
"font_class": "dianhua",
|
||||||
|
"unicode": "e61b",
|
||||||
|
"unicode_decimal": 58907
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "658000",
|
||||||
|
"name": "地址",
|
||||||
|
"font_class": "dizhi",
|
||||||
|
"unicode": "e652",
|
||||||
|
"unicode_decimal": 58962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "908052",
|
||||||
|
"name": "姓名",
|
||||||
|
"font_class": "xingming",
|
||||||
|
"unicode": "e635",
|
||||||
|
"unicode_decimal": 58933
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "17805508",
|
||||||
|
"name": "top_联系方式",
|
||||||
|
"font_class": "top_lianxifangshi",
|
||||||
|
"unicode": "e612",
|
||||||
|
"unicode_decimal": 58898
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "18319239",
|
||||||
|
"name": "童装性别",
|
||||||
|
"font_class": "tongzhuangxingbie",
|
||||||
|
"unicode": "e614",
|
||||||
|
"unicode_decimal": 58900
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "765406",
|
||||||
|
"name": "首页",
|
||||||
|
"font_class": "home",
|
||||||
|
"unicode": "e68a",
|
||||||
|
"unicode_decimal": 59018
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "145433",
|
||||||
|
"name": "设置",
|
||||||
|
"font_class": "shezhi",
|
||||||
|
"unicode": "e62a",
|
||||||
|
"unicode_decimal": 58922
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "2959116",
|
||||||
|
"name": "账号管理",
|
||||||
|
"font_class": "zhanghaoguanli",
|
||||||
|
"unicode": "e639",
|
||||||
|
"unicode_decimal": 58937
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "3702619",
|
||||||
|
"name": "角色管理",
|
||||||
|
"font_class": "navicon-jsgl",
|
||||||
|
"unicode": "e640",
|
||||||
|
"unicode_decimal": 58944
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "5283349",
|
||||||
|
"name": "菜单",
|
||||||
|
"font_class": "caidan",
|
||||||
|
"unicode": "e65d",
|
||||||
|
"unicode_decimal": 58973
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7720058",
|
||||||
|
"name": "菜单",
|
||||||
|
"font_class": "caidan1",
|
||||||
|
"unicode": "e609",
|
||||||
|
"unicode_decimal": 58889
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "12184880",
|
||||||
|
"name": "部门",
|
||||||
|
"font_class": "bumen",
|
||||||
|
"unicode": "e686",
|
||||||
|
"unicode_decimal": 59014
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "6415223",
|
||||||
|
"name": "版权",
|
||||||
|
"font_class": "banquan",
|
||||||
|
"unicode": "e66d",
|
||||||
|
"unicode_decimal": 58989
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "12990693",
|
||||||
|
"name": "登陆-box-线",
|
||||||
|
"font_class": "denglu-box-xian",
|
||||||
|
"unicode": "e89f",
|
||||||
|
"unicode_decimal": 59551
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "201577",
|
||||||
|
"name": "3.1电话",
|
||||||
|
"font_class": "31dianhua",
|
||||||
|
"unicode": "e600",
|
||||||
|
"unicode_decimal": 58880
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "1831590",
|
||||||
|
"name": "个人信息",
|
||||||
|
"font_class": "gerenxinxi",
|
||||||
|
"unicode": "e641",
|
||||||
|
"unicode_decimal": 58945
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7461023",
|
||||||
|
"name": "全屏",
|
||||||
|
"font_class": "quanping",
|
||||||
|
"unicode": "e632",
|
||||||
|
"unicode_decimal": 58930
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "9656282",
|
||||||
|
"name": "个人信息",
|
||||||
|
"font_class": "gerenxinxi1",
|
||||||
|
"unicode": "e603",
|
||||||
|
"unicode_decimal": 58883
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "14329730",
|
||||||
|
"name": "关机",
|
||||||
|
"font_class": "guanji",
|
||||||
|
"unicode": "e689",
|
||||||
|
"unicode_decimal": 59017
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "19457229",
|
||||||
|
"name": "email",
|
||||||
|
"font_class": "youxiang",
|
||||||
|
"unicode": "e6b0",
|
||||||
|
"unicode_decimal": 59056
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "508253",
|
||||||
|
"name": "密码",
|
||||||
|
"font_class": "mima",
|
||||||
|
"unicode": "e60f",
|
||||||
|
"unicode_decimal": 58895
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "8455373",
|
||||||
|
"name": "验证码",
|
||||||
|
"font_class": "yanzhengma",
|
||||||
|
"unicode": "e619",
|
||||||
|
"unicode_decimal": 58905
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "10232786",
|
||||||
|
"name": "用户名",
|
||||||
|
"font_class": "yonghuming",
|
||||||
|
"unicode": "e78f",
|
||||||
|
"unicode_decimal": 59279
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "21758126",
|
||||||
|
"name": "用户登陆统计",
|
||||||
|
"font_class": "yonghudenglutongjigongju",
|
||||||
|
"unicode": "e6ae",
|
||||||
|
"unicode_decimal": 59054
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
frontEnd/src/assets/css/aliIcon/iconfont.ttf
Normal file
BIN
frontEnd/src/assets/css/aliIcon/iconfont.woff
Normal file
BIN
frontEnd/src/assets/css/aliIcon/iconfont.woff2
Normal file
73
frontEnd/src/assets/css/default.scss
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*图标库*/
|
||||||
|
@import url("./aliIcon/iconfont.css");
|
||||||
|
/*图标库*/
|
||||||
|
/*默认背景颜色*/
|
||||||
|
.default-bckcolor {
|
||||||
|
background-color: #f6f8fa !important;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /* 自定义滚动条轨道 */
|
||||||
|
// *::-webkit-scrollbar {
|
||||||
|
// width: 7px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /* 自定义滚动条滑块 */
|
||||||
|
// ::-webkit-scrollbar-thumb {
|
||||||
|
// width: 2px;
|
||||||
|
// background-color: #555;
|
||||||
|
// border: 1px solid #e8e9ea;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.mask {
|
||||||
|
position: fixed;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: rgba(#000, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*水平居中*/
|
||||||
|
.inline-center {
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
/*垂直居中*/
|
||||||
|
.height-center {
|
||||||
|
display: flex !important;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.flex-center {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-menu {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
align-items: center;
|
||||||
|
.ui-menu-item {
|
||||||
|
padding: 0 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: all 0.5s;
|
||||||
|
&:hover {
|
||||||
|
background-color: #e8e9ea;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.width-100 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.height-100 {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
133
frontEnd/src/assets/css/element.scss
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
$base: #306dbb;
|
||||||
|
@forward "element-plus/theme-chalk/src/common/var.scss" with (
|
||||||
|
$colors: (
|
||||||
|
"white": #ffffff,
|
||||||
|
"black": #000000,
|
||||||
|
"primary": (
|
||||||
|
"base": $base,
|
||||||
|
),
|
||||||
|
"success": (
|
||||||
|
"base": #248067,
|
||||||
|
),
|
||||||
|
"warning": (
|
||||||
|
"base": #fb8b05,
|
||||||
|
),
|
||||||
|
"danger": (
|
||||||
|
"base": #f04b22,
|
||||||
|
),
|
||||||
|
"error": (
|
||||||
|
"base": #ec2b24,
|
||||||
|
),
|
||||||
|
"info": (
|
||||||
|
"base": #909399,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
$switch: (
|
||||||
|
"on-color": "#248067",
|
||||||
|
),
|
||||||
|
$dialog: (
|
||||||
|
"border-radius": "8px",
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
@use "element-plus/theme-chalk/src/index.scss" as *;
|
||||||
|
|
||||||
|
.el-menu {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
// .el-dialog__header{
|
||||||
|
// background-color: $base;
|
||||||
|
// color: #fff;
|
||||||
|
// margin-right: 0;
|
||||||
|
// border-radius: 7px;
|
||||||
|
// border-bottom-left-radius: 0;
|
||||||
|
// border-bottom-right-radius: 0;
|
||||||
|
// .el-dialog__title{
|
||||||
|
// color: #fff;
|
||||||
|
// }
|
||||||
|
// .el-dialog__headerbtn{
|
||||||
|
// .el-dialog__close{
|
||||||
|
// color: #fff;
|
||||||
|
// font-size: 18px;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
.el-dialog__body {
|
||||||
|
padding-bottom: 15px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table {
|
||||||
|
th.el-table__cell {
|
||||||
|
background-color: #f1f3f4;
|
||||||
|
&:first-child {
|
||||||
|
border-top-left-radius: 6px;
|
||||||
|
border-bottom-left-radius: 6px;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
border-top-right-radius: 6px;
|
||||||
|
border-bottom-right-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-table__header-wrapper tr th.el-table-fixed-column--right,
|
||||||
|
.el-table.is-scrolling-none th.el-table-fixed-column--right {
|
||||||
|
background-color: #f1f3f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-descriptions {
|
||||||
|
.el-descriptions__header {
|
||||||
|
position: relative;
|
||||||
|
background-color: #e8eef5;
|
||||||
|
padding: 6px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
.el-descriptions__title {
|
||||||
|
padding-left: 12px;
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
width: 5px;
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
background-color: #15559a;
|
||||||
|
border-radius: 8px;
|
||||||
|
animation: menueLeftLine 0.45s ease;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-dialog {
|
||||||
|
.el-dialog__header {
|
||||||
|
padding-top: 10px !important;
|
||||||
|
padding-bottom: 35px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus,
|
||||||
|
button:focus-visible {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-message-box__container {
|
||||||
|
flex-direction: column;
|
||||||
|
.el-message-box__status {
|
||||||
|
svg {
|
||||||
|
transform: scale(2.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-message-box__btns {
|
||||||
|
justify-content: center;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes menueLeftLine {
|
||||||
|
0% {
|
||||||
|
height: 0%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
frontEnd/src/assets/css/reset.scss
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
body,html {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||