------------------------ Bancai.java ------------------------
package com.kucun.data.entity;
import java.lang.annotation.Annotation;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import com.kucun.data.entity.DTO.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
/**
板材
@author Administrator
*/
@Entity
@Table(name=“bancai”)
@JsonSerialize(using = FullEntitySerializer.class)
@UniqueEntity(
repositoryName = “bancai”,
fields = {“houdu”, “caizhi”, “mupi1”, “mupi2”},
message = “板材组合已存在”
)
public class Bancai extends EntityBasis {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne( fetch = FetchType.LAZY)
@JoinColumn(name = “caizhi_id”) //
private Caizhi caizhi;
@ManyToOne( fetch = FetchType.LAZY)
@JoinColumn(name = “mupi1_id”)
private Mupi mupi1;
@ManyToOne( fetch = FetchType.LAZY)
@JoinColumn(name = “mupi2_id”)
private Mupi mupi2;
private Double houdu;
@OneToOne(
cascade = CascadeType.ALL,
orphanRemoval = true, // 添加此配置
fetch = FetchType.LAZY
)
@JoinColumn(name = “kucun_id”, referencedColumnName = “id”)
private Kucun kucun;
public Kucun getKucun() {
return kucun;
}
public void setKucun(Kucun kucun) {
this.kucun = kucun;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Caizhi getCaizhi() {
return caizhi;
}
public void setCaizhi(Caizhi caizhi) {
this.caizhi = caizhi;
}
public Mupi getMupi1() {
return mupi1;
}
public void setMupi1(Mupi mupi1) {
this.mupi1 = mupi1;
}
public Mupi getMupi2() {
return mupi2;
}
public void setMupi2(Mupi mupi2) {
this.mupi2 = mupi2;
}
public Double getHoudu() {
return houdu;
}
public void setHoudu(Double houdu) {
this.houdu = houdu;
}
public Bancai(int id, Caizhi caizhi, Mupi mupi1, Mupi mupi2, Double houdu) {
super();
this.id = id;
this.caizhi = caizhi;
this.mupi1 = mupi1;
this.mupi2 = mupi2;
this.houdu = houdu;
}
public Bancai() {
super();
}
}
------------------------ Caizhi.java ------------------------
package com.kucun.data.entity;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.FullEntitySerializer;
import com.kucun.data.entity.DTO.UniqueEntity;
/**
板材材质
@author Administrator
*/
@Entity
@Table(name=“caizhi”, uniqueConstraints = {
@UniqueConstraint(columnNames = “name”)
})
@UniqueEntity(
repositoryName = “caizhi”,
fields = {“name”},
message = “材质已存在”
)
@JsonSerialize(using = FullEntitySerializer.class)
public class Caizhi extends EntityBasis{
@OneToMany(mappedBy="caizhi") private List<Bancai> bancai; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Bancai> getBancai() { return bancai; } public void setBancai(List<Bancai> bancai) { this.bancai = bancai; }
}
------------------------ Chanpin.java ------------------------
package com.kucun.data.entity;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.*;
/**
产品类
@author Administrator
*/
@Entity
@Table(name=“chanpin”, uniqueConstraints = {
@UniqueConstraint(columnNames = “bianhao”)
})
@JsonSerialize(using = FullEntitySerializer.class)
@UniqueEntity(
repositoryName = “chanpin”,
fields = {“bianhao”},
message = “该产品已存在”
)
public class Chanpin extends EntityBasis {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// 关联订单产品
@OneToMany(
mappedBy = “chanpin”,
cascade = CascadeType.ALL,
fetch = FetchType.LAZY
)
private List<Dingdan_chanpin> dingdan_chanpin;
private String bianhao;
@OneToMany( mappedBy = "chanpin", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true ) private List<Chanpin_zujian> chanpin_zujian; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBianhao() { return bianhao; } public void setBianhao(String bianhao) { this.bianhao = bianhao; } public List<Dingdan_chanpin> getDingdan_chanpin() { return dingdan_chanpin; } public void setDingdan_chanpin(List<Dingdan_chanpin> dingdan_chanpin) { this.dingdan_chanpin = dingdan_chanpin; } public List<Chanpin_zujian> getChanpin_zujian() { return chanpin_zujian; } public void setChanpin_zujian(List<Chanpin_zujian> chanpin_zujian) { this.chanpin_zujian = chanpin_zujian; }
}
------------------------ Chanpin_zujian.java ------------------------
package com.kucun.data.entity;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.FullEntitySerializer;
import com.kucun.data.entity.DTO.UniqueEntity;
/**
产品组件关联类
@author Administrator
*/
@Entity
@Table(name=“chanpin_zujian”)
@JsonSerialize(using = FullEntitySerializer.class)
@UniqueEntity(
repositoryName = “chanpin_zhujian”,
fields = { “chanpin”, “zujian”},
message = “产品下也有该组件”
)
public class Chanpin_zujian extends EntityBasis {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// 关联到产品
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = “chanpin_id”)
private Chanpin chanpin;
// 关联到组件 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "zujian_id") private Zujian zujian; // 关联到板材 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "bancai_id") private Bancai bancai; //一张板材生产多少组件 private Double one_howmany; //生产多少组件 private Double zujianshu; public Double getZujianshu() { return zujianshu; } public void setZujianshu(Double zujianshu) { this.zujianshu = zujianshu; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Chanpin getChanpin() { return chanpin; } public void setChanpin(Chanpin chanpin) { this.chanpin = chanpin; } public Zujian getZujian() { return zujian; } public void setZujian(Zujian zujian) { this.zujian = zujian; } public Bancai getBancai() { return bancai; } public void setBancai(Bancai bancai) { this.bancai = bancai; } public Double getOne_howmany() { return one_howmany; } public void setOne_howmany(Double one_howmany) { this.one_howmany = one_howmany; } public Chanpin_zujian() { super(); // TODO Auto-generated constructor stub }
}
------------------------ Dingdan.java ------------------------
package com.kucun.data.entity;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.FullEntitySerializer;
import com.kucun.data.entity.DTO.UniqueEntity;
/**
订单
@author Administrator
*/
@Entity
@Table(name=“dingdan”, uniqueConstraints = {
@UniqueConstraint(columnNames = “number”)
})
@UniqueEntity(
repositoryName = “dingdan”,
fields = {“numder”},
message = “该订单已存在”
)
@JsonSerialize(using = FullEntitySerializer.class)
public class Dingdan extends EntityBasis{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
//订单号
private String number;
private Date xiadan;
private Date jiaohuo;
@OneToMany(
mappedBy = “dingdan”,
cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
orphanRemoval = true
)
private List<Dingdan_chanpin> dingdan_chanpin;
public Date getXiadan() {
return xiadan;
}
public void setXiadan(Date xiadan) {
this.xiadan = xiadan;
}
public Date getJiaohuo() {
return jiaohuo;
}
public void setJiaohuo(Date jiaohuo) {
this.jiaohuo = jiaohuo;
}
public List<Dingdan_chanpin> getDingdan_chanpin() {
return dingdan_chanpin;
}
public void setDingdan_chanpin(List<Dingdan_chanpin> dingdan_chanpins) {
this.dingdan_chanpin = dingdan_chanpins;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Dingdan(Integer id, String number) {
super();
this.id = id;
this.number = number;
}
public Dingdan() {
super();
// TODO Auto-generated constructor stub
}
}
------------------------ Dingdan_chanpin.java ------------------------
package com.kucun.data.entity;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.FullEntitySerializer;
import com.kucun.data.entity.DTO.UniqueEntity;
/**
订单和产品关联
@author Administrator
*/
@Entity
@Table(name=“dingdan_chanpin”)
@UniqueEntity(
repositoryName = “dingdan_chanpin”,
fields = {“dingdan”,“chanpin”},
message = “订单下已有该产品”
)
@JsonSerialize(using = FullEntitySerializer.class)
public class Dingdan_chanpin extends EntityBasis {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
//产品信息
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = “dingdan_id”) // 指
private Dingdan dingdan; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "chanpin_id") // 指 private Chanpin chanpin; private Integer shuliang;//产品数量; public Chanpin getChanpin() { return chanpin; } public void setChanpin(Chanpin chanpin) { this.chanpin = chanpin; } public Integer getShuliang() { return shuliang; } public void setShuliang(Integer shuliang) { this.shuliang = shuliang; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Dingdan getDingdan() { return dingdan; } public void setDingdan(Dingdan dingdan) { this.dingdan = dingdan; } public Chanpin getChanping() { return chanpin; } public void setChanping(Chanpin chanping) { this.chanpin = chanping; }
}
------------------------ EntityBasis.java ------------------------
package com.kucun.data.entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public abstract class EntityBasis implements EntityBasisId {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) { this.id = id; }
}
------------------------ EntityBasisId.java ------------------------
package com.kucun.data.entity;
public interface EntityBasisId {
Integer getId();
void setId(Integer id);
}
------------------------ Information.java ------------------------
package com.kucun.data.entity;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
通信类
@author Administrator
*/
public class Information {
private static final ObjectMapper mapper = new ObjectMapper();
private Integer Status ;
private String text;
private Object data;
public Integer getStatus() {
return Status;
}
public void setStatus(Integer status) {
Status = status;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Information(Integer status, String text, Object data) {
super();
Status = status;
this.text = text;
this.data = data;
}
@SuppressWarnings({“unchecked”,“rawtypes”})
public Information(Integer status, String text, String data, Class T) throws Exception {
super();
Status = status;
this.text = text;
this.data = fromJson(data,T);
}
public Information() {
super();
// TODO Auto-generated constructor stub
}
public String DataJson() throws JsonProcessingException {
// Java对象转JSON
return mapper.writeValueAsString(this);
}
@SuppressWarnings(“unchecked”)
public T fromJson(String json, Class clazz) throws Exception {
data= mapper.readValue(json, clazz);
return (T) data;
}
public static Information NewSuccess(Object data) {
return new Information(200, "success", data); } public static Information NewSuccess(String data) { return new Information(200, "success", data); } public static Information Newfail(Integer status,String text,Object data) { return new Information(status, "success", data); } public static Information NewFail(int i, String string) { // TODO Auto-generated method stub return new Information(i,string,null); } public static Information NewFail( String string) { // TODO Auto-generated method stub return new Information(400,string,null); }
}
------------------------ Jinhuo.java ------------------------
package com.kucun.data.entity;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.FullEntitySerializer;
@Entity
@JsonSerialize(using = FullEntitySerializer.class)
public class Jinhuo extends EntityBasis{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(optional=true)
private Dingdan dingdan; @ManyToOne(optional=true) private Chanpin chanpin; @ManyToOne(optional=true) private Zujian zujian; @ManyToOne(optional=true) private Bancai bancai; private Integer shuliang; private Date date; @ManyToOne private User user; public Jinhuo(Integer id, Dingdan dingdan, Chanpin chanpin, Zujian zujian, Bancai bancai, Integer shuliang, Date date, User user) { super(); this.id = id; this.dingdan = dingdan; this.chanpin = chanpin; this.zujian = zujian; this.bancai = bancai; this.shuliang = shuliang; this.date = date; this.user = user; } public Jinhuo() { super(); // TODO Auto-generated constructor stub } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Dingdan getDingdan() { return dingdan; } public void setDingdan(Dingdan dingdan) { this.dingdan = dingdan; } public Chanpin getChanpin() { return chanpin; } public void setChanpin(Chanpin chanpin) { this.chanpin = chanpin; } public Zujian getZujian() { return zujian; } public void setZujian(Zujian zujian) { this.zujian = zujian; } public Bancai getBancai() { return bancai; } public void setBancai(Bancai bancai) { this.bancai = bancai; } public Integer getShuliang() { return shuliang; } public void setShuliang(Integer shuliang) { this.shuliang = shuliang; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public User getUser() { return user; } public void setUser(User user) { this.user = user; }
}
------------------------ Kucun.java ------------------------
package com.kucun.data.entity;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.FullEntitySerializer;
/**
库存
@author Administrator
*/
@Entity
@JsonSerialize(using = FullEntitySerializer.class)
public class Kucun extends EntityBasis{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Integer shuliang; @OneToOne(fetch = FetchType.LAZY) // 正确映射 Bancai 实体 @JoinColumn(name = "bancai_id", referencedColumnName = "id") private Bancai bancai; // 新增:库存归属订单(可为空) @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dingdan_id") private Dingdan reservedOrder;
public Integer getId() {
return id;
}
public Dingdan getReservedOrder() {
return reservedOrder;
}
public void setReservedOrder(Dingdan reservedOrder) {
this.reservedOrder = reservedOrder;
}
public void setId(Integer id) {
this.id = id;
}
public Bancai getBancai() {
return bancai;
}
public void setBancai(Bancai bancai) {
this.bancai = bancai;
}
public Integer getShuliang() {
return shuliang;
}
public void setShuliang(Integer shuliang) {
this.shuliang = shuliang;
}
public Kucun(Integer id, Bancai bancai, Integer shuliang) {
super();
this.id = id;
this.bancai = bancai;
this.shuliang = shuliang;
}
public Kucun() {
super();
// TODO Auto-generated constructor stub
}
}
------------------------ Mupi.java ------------------------
package com.kucun.data.entity;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.FullEntitySerializer;
/**
木皮
@author Administrator
*/
@Entity
@Table(name=“mupi”, uniqueConstraints = {
@UniqueConstraint(columnNames = “name”)
})
@JsonSerialize(using = FullEntitySerializer.class)
public class Mupi extends EntityBasis{
/** * 是否有油漆 */ @Column(name="you") @Type(type = "org.hibernate.type.BooleanType") private Boolean you; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } // 添加 OneToMany 映射 @OneToMany(mappedBy = "mupi1") // 指向 Bancai 中的 mupi1 字段 private List<Bancai> bancaisForMupi1; @OneToMany(mappedBy = "mupi2") // 指向 Bancai 中的 mupi2 字段 private List<Bancai> bancaisForMupi2; public List<Bancai> getBancaisForMupi1() { return bancaisForMupi1; } public void setBancaisForMupi1(List<Bancai> bancaisForMupi1) { this.bancaisForMupi1 = bancaisForMupi1; } public List<Bancai> getBancaisForMupi2() { return bancaisForMupi2; } public void setBancaisForMupi2(List<Bancai> bancaisForMupi2) { this.bancaisForMupi2 = bancaisForMupi2; } public Mupi() { super(); } public Boolean getYou() { return you; } public void setYou(Boolean you) { this.you = you; }
}
------------------------ SimpleEntity.java ------------------------
package com.kucun.data.entity;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public abstract class SimpleEntity implements EntityBasisId{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false, unique = true) private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // Getters and Setters...
}
------------------------ User.java ------------------------
package com.kucun.data.entity;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.FullEntitySerializer;
/**
用户
@author Administrator
/
@Entity
@Table(name=“user”)
@JsonSerialize(using = FullEntitySerializer.class)
public class User extends EntityBasis{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
/*
* 名字
/
@Column(nullable=false)
private String name;
/*
* 账号
/
@Column(nullable=false)
private String andy;
/*
* 密码
/
@Column(nullable=false)
private String pass;
/*
* 权限
*/
@Column(nullable=false)
private int role;
public User() { super(); } public User(int id, String name, String andy, String pass) { super(); this.id = id; this.name = name; this.andy = andy; this.pass = pass; } public Integer getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAndy() { return andy; } public void setAndy(String andy) { this.andy = andy; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } public int getRole() { System.out.println(role); return role; } public void setRole(int role) { this.role = role; } @Override public String toString() { return "{id:" + id + ", name:" + name + ", andy:" + andy + ", pass:" + pass + ", role:" + role + "}"; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return Objects.equals(id, user.id) && Objects.equals(name, user.name) && Objects.equals(andy, user.andy)&& Objects.equals(role, user.role); //添加所有属性比较 } @Override public int hashCode() { return Objects.hash(id, name, andy,pass,role); } @Override public void setId(Integer id) { // TODO Auto-generated method stub }
}
------------------------ Zujian.java ------------------------
package com.kucun.data.entity;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.kucun.data.entity.DTO.FullEntitySerializer;
@Entity
@JsonSerialize(using = FullEntitySerializer.class)
public class Zujian extends EntityBasis{
private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } // 反向关联到产品组件 @OneToMany( mappedBy = "zujian", cascade = CascadeType.ALL, fetch = FetchType.LAZY ) private List<Chanpin_zujian> chanping_zujian; public List<Chanpin_zujian> getChanping_zujian() { return chanping_zujian; } public void setChanping_zujian(List<Chanpin_zujian> chanping_zujian) { this.chanping_zujian = chanping_zujian; }
}
------------------------ DataManager.js ------------------------
//{ 实体类的关联和属性列表
// “entities”: {
// “Dingdan”: {
// “properties”: {
// “id”: “Integer”,
// “number”: “String”,
// “xiadan”: “Date”,
// “jiaohuo”: “Date”,
// “dingdan_chanpins”: “List<Dingdan_chanpin> (OneToMany)”,
// “dingdan_chanpins_zujians”: “List<Dingdan_chanpin_zujian> (OneToMany)”
// },
// “relations”: [
// “关联订单产品(Dingdan_chanpin)”,
// “关联订单组件(Dingdan_chanpin_zujian)”
// ]
// },
// “Dingdan_chanpin”: {
// “properties”: {
// “id”: “Integer”,
// “shuliang”: “Integer”
// },
// “relations”: [
// “多对一关联订单(Dingdan)”,
// “多对一关联产品(Chanpin)”
// ]
// },
// “Dingdan_chanpin_zujian”: {
// “properties”: {
// “id”: “Integer”,
// “shuliang”: “Integer”
// },
// “relations”: [
// “多对一关联订单(Dingdan)”,
// “多对一关联组件(Chanpin_zujian)”,
// “多对一关联板材(Bancai)”
// ]
// },
// “Jinhuo”: {
// “properties”: {
// “id”: “Integer”,
// “shuliang”: “Integer”,
// “date”: “Date”
// },
// “relations”: [
// “多对一关联订单(Dingdan)”,
// “多对一关联产品(Chanpin)”,
// “多对一关联组件(Zujian)”,
// “多对一关联板材(Bancai)”,
// “多对一关联用户(User)”
// ]
// },
// “Kucun”: {
// “properties”: {
// “id”: “Integer”,
// “shuliang”: “Long”
// },
// “relations”: [
// “一对一关联板材(Bancai)”
// ]
// },
// “Mupi”: {
// “properties”: {
// “id”: “Integer”,
// “name”: “String”,
// “you”: “Boolean”
// },
// “relations”: [
// “被板材关联(Bancai - mupi1/mupi2)”
// ]
// },
// “User”: {
// “properties”: {
// “id”: “Integer”,
// “name”: “String”,
// “andy”: “String”,
// “pass”: “String”,
// “role”: “int”
// }
// },
// “Zujian”: {
// “properties”: {
// “id”: “Integer”,
// “name”: “String”
// },
// “relations”: [
// “一对多关联产品组件(Chanpin_zujian)”
// ]
// },
// “Bancai”: {
// “properties”: {
// “id”: “Integer”,
// “houdu”: “Double”
// },
// “relations”: [
// “多对一关联材质(Caizhi)”,
// “多对一关联木皮(Mupi - mupi1/mupi2)”,
// “一对一关联库存(Kucun)”
// ]
// },
// “Caizhi”: {
// “properties”: {
// “id”: “Integer”,
// “name”: “String”
// },
// “relations”: [
// “一对多关联板材(Bancai)”
// ]
// },
// “Chanpin”: {
// “properties”: {
// “id”: “Integer”,
// “bianhao”: “String”
// },
// “relations”: [
// “一对多关联订单产品(Dingdan_chanpin)”,
// “一对多关联产品组件(Chanpin_zujian)”
// ]
// },
// “Chanpin_zujian”: {
// “properties”: {
// “id”: “Integer”,
// “one_howmany”: “Double”
// },
// “relations”: [
// “多对一关联产品(Chanpin)”,
// “多对一关联组件(Zujian)”,
// “多对一关联板材(Bancai)”
// ]
// }
// },
// “relationsSummary”: [
// “订单(Dingdan) 1:N 订单产品(Dingdan_chanpin)”,
// “订单(Dingdan) 1:N 订单组件(Dingdan_chanpin_zujian)”,
// “产品(Chanpin) 1:N 产品组件(Chanpin_zujian)”,
// “组件(Zujian) 1:N 产品组件(Chanpin_zujian)”,
// “板材(Bancai) 1:1 库存(Kucun)”,
// “材质(Caizhi) 1:N 板材(Bancai)”
// ]
//}
/**
优化后的关联解析函数(解决空值问题并支持多层关联)
@param {Object} data - 后端原始数据
@returns {Object} 处理后的完整关联数据
*/
function resolveDataReferences(data) {
// 创建ID映射表(带空值保护)
const idMaps = {};
Object.keys(data).forEach(key => {
if (Array.isArray(data[key])) {
idMaps[key] = new Map();
data[key].forEach(item => item.id && idMaps[key].set(item.id, item));
}
});
// 通用关联解析方法(支持多层关联)
const resolveRef = (sourceArray, sourceKey, targetKey, refProperty) => {
if (!Array.isArray(sourceArray)) return;
sourceArray.forEach(item => { const refObj = item[refProperty]; if (refObj && refObj.id && idMaps[targetKey]) { const target = idMaps[targetKey].get(refObj.id); if (target) { // 建立正向引用 item[refProperty] = target; // 建立反向引用(自动创建关联数组) const reverseProp = sourceKey.endsWith('s') ? sourceKey.slice(0, -1) + '_list' : sourceKey + '_list'; if (!target[reverseProp]) target[reverseProp] = []; if (!target[reverseProp].includes(item)) { target[reverseProp].push(item); } } } });
};
// 处理所有定义的关联关系
// 订单 ↔ 订单产品
if (data.dingdans && data.dingdan_chanpins) {
resolveRef(data.dingdan_chanpins, ‘dingdans’, ‘dingdans’, ‘dingdan’);
}
// 订单 ↔ 订单组件
if (data.dingdans && data.dingdan_chanpin_zujians) {
resolveRef(data.dingdan_chanpin_zujians, ‘dingdans’, ‘dingdans’, ‘dingdan’);
}
// 产品 ↔ 产品组件
if (data.chanpins && data.chanpin_zujians) {
resolveRef(data.chanpin_zujians, ‘chanpins’, ‘chanpins’, ‘chanpin’);
}
// 组件 ↔ 产品组件
if (data.zujians && data.chanpin_zujians) {
resolveRef(data.chanpin_zujians, ‘zujians’, ‘zujians’, ‘zujian’);
}
// 材质 ↔ 板材
if (data.caizhis && data.bancais) {
resolveRef(data.bancais, ‘caizhis’, ‘caizhis’, ‘caizhi’);
}
// 板材 ↔ 库存(一对一)
if (data.bancais && data.kucuns) {
resolveRef(data.bancais, ‘kucuns’, ‘kucuns’, ‘kucun’);
resolveRef(data.kucuns, ‘bancais’, ‘bancais’, ‘bancai’);
}
// 板材 ↔ 木皮(mupi1/mupi2)
if (data.bancais && data.mupis) {
resolveRef(data.bancais, ‘mupis’, ‘mupis’, ‘mupi1’);
resolveRef(data.bancais, ‘mupis’, ‘mupis’, ‘mupi2’);
}
// 订单产品 ↔ 产品
if (data.dingdan_chanpins && data.chanpins) {
resolveRef(data.dingdan_chanpins, ‘chanpins’, ‘chanpins’, ‘chanpin’);
}
// 订单组件 ↔ 产品组件
if (data.dingdan_chanpin_zujians && data.chanpin_zujians) {
resolveRef(data.dingdan_chanpin_zujians, ‘chanpin_zujians’, ‘chanpin_zujians’, ‘chanpin_zujian’);
}
// 订单组件 ↔ 板材
if (data.dingdan_chanpin_zujians && data.bancais) {
resolveRef(data.dingdan_chanpin_zujians, ‘bancais’, ‘bancais’, ‘bancai’);
}
// 产品组件 ↔ 板材
if (data.chanpin_zujians && data.bancais) {
resolveRef(data.chanpin_zujians, ‘bancais’, ‘bancais’, ‘bancai’);
}
// 进货 ↔ 相关实体
if (data.jinhuos) {
[‘dingdan’, ‘chanpin’, ‘zujian’, ‘bancai’, ‘user’].forEach(entity => {
const plural = entity + ‘s’;
if (data[plural]) {
resolveRef(data.jinhuos, plural, plural, entity);
}
});
}
// 新增:计算订单可用板材
if (data.dingdans) {
data.dingdans.forEach(dingdan => {
// 初始化订单可用板材
dingdan.availableBancais = {};
// 遍历订单中的所有产品 if (dingdan.dingdan_chanpin_list) { dingdan.dingdan_chanpin_list.forEach(dc => { if (dc.chanpin && dc.chanpin.chanpin_zujian_list) { // 遍历产品的所有组件 dc.chanpin.chanpin_zujian_list.forEach(cz => { if (cz.bancai) { const bancaiId = cz.bancai.id; // 计算组件所需板材数量 = 产品数量 × 组件数量比例 const required = dc.shuliang * (cz.zujianshu || 1); if (!dingdan.availableBancais[bancaiId]) { dingdan.availableBancais[bancaiId] = { bancai: cz.bancai, required: 0, available: 0 }; } dingdan.availableBancais[bancaiId].required += required; } }); } }); } // 遍历订单中的所有直接组件 if (dingdan.dingdan_chanpin_zujian_list) { dingdan.dingdan_chanpin_zujian_list.forEach(dz => { if (dz.bancai) { const bancaiId = dz.bancai.id; const required = dz.shuliang; if (!dingdan.availableBancais[bancaiId]) { dingdan.availableBancais[bancaiId] = { bancai: dz.bancai, required: 0, available: 0 }; } dingdan.availableBancais[bancaiId].required += required; } }); } // 计算可用数量(从库存中减去其他订单预留量) Object.values(dingdan.availableBancais).forEach(info => { if (info.bancai.kucun) { // 获取板材总库存 let totalAvailable = info.bancai.kucun.shuliang; // 减去其他订单预留量 data.dingdans.forEach(otherDingdan => { if (otherDingdan.id !== dingdan.id && otherDingdan.availableBancais?.[info.bancai.id]) { totalAvailable -= otherDingdan.availableBancais[info.bancai.id].required; } }); // 确保可用量不小于0 info.available = Math.max(0, totalAvailable); } }); });
}
return data;
}
function _resolveDataReferences(data) {
// 获取 data 对象的所有顶层键
const keys = Object.keys(data);
// 遍历每个顶层键(如 users, posts 等) for (const key of keys) { const entities = data[key]; // 遍历该顶层键下的每个实体(如每个 user 或 post) for (const entity of entities) { // 遍历实体的每个属性 for (const attribute in entity) { if (entity.hasOwnProperty(attribute)) { var trpe=attribute.replace(/\d/g, ''); // 确保属性属于当前实体 if (Array.isArray(entity[attribute])) { if(data[trpe]==null){ trpe+="s" } // 如果属性是一个数组,则将数组中的每个 ID 替换为对应的实际对象 entity[attribute] = entity[attribute].map(item => data[trpe ]?.find(updateItem => updateItem.id === item.id) || item ); } else if (typeof entity[attribute] === "object" && entity[attribute] !== null) { // 如果属性是一个对象,则将其替换为对应的实际对象 entity[attribute] = data[trpe + "s"]?.find(updateItem => updateItem.id === entity[attribute].id); } } } } } console.log(data) return data;
}
/**
数据管理器类,负责与后端API通信并管理数据
*/
class DataManager {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.data = {
bancais: [],
dingdans: [],
mupis: [],
chanpins: [],
kucuns: [],
chanpin_zujians: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [], jinhuos: [] }; this.isSyncing = false; this.lastSync = null; this.callbacks = { all: [], bancais: [], dingdan: [], mupi: [], chanpin: [], kucun: [], chanpin_zujian: [], zujian: [], caizhi: [], dingdan_chanpin: [], user: [], jinhuo: [] }; this.syncQueue = Promise.resolve();
}
/**
获取所有数据
@returns {Promise} 是否成功
*/
async fetchAll() {
console.log(this)
try {
const response = await fetch(${this.baseUrl}/app/all);
if (!response.ok) throw new Error(‘Network response was not ok’);
const result = await response.json();
if (result.status !== 200) throw new Error(result.text || ‘API error’);
const resolvedData = resolveDataReferences(result.data);
// 更新本地数据
Object.keys(this.data).forEach(key => {
if (resolvedData[key]) {
this.data[key] = resolvedData[key];
}
});
this.lastSync = new Date();
// 关键改进:数据更新后触发刷新回调
this.triggerCallbacks(‘refresh’, ‘all’, this.data);
return true;
} catch (error) {
console.error(‘Fetch error:’, error);
// 触发错误回调
this.triggerCallbacks(‘fetch_error’, ‘all’, { error });
return false;
}
}
/**
注册回调函数
@param {string} entity - 实体类型(如’bancai’)或’all’表示全局回调
@param {Function} callback - 回调函数,参数为(operation, data)
*/
registerCallback(entity, callback) {
if (!this.callbacks[entity]) {
this.callbacks[entity] = [];
}
this.callbacks[entity].push(callback);
}
/**
移除回调函数
@param {string} entity - 实体类型单数性质
@param {Function} callback - 要移除的回调函数
*/
unregisterCallback(entity, callback) {
if (!this.callbacks[entity]) return;
const index = this.callbacks[entity].indexOf(callback); if (index !== -1) { this.callbacks[entity].splice(index, 1); }
}
/**
触发回调
@param {string} operation - 操作类型(‘add’, ‘update’, ‘delete’)
@param {string} entity - 实体类型单数性质
@param {Object} data - 相关数据
*/
triggerCallbacks(operation, entity, data) {
// 触发全局回调
this.callbacks.all.forEach(cb => cb(operation, entity, data));
// 触发特定实体回调 if (this.callbacks[entity]) { this.callbacks[entity].forEach(cb => cb(operation, data)); }
}
/**
执行CRUD操作并触发回调
*/
async crudOperation(operation, entity, data) {
try {
const response = await fetch(${this.baseUrl}/app/${operation}/${entity}, {
method: ‘POST’,
headers: {‘Content-Type’: ‘application/json’},
body: JSON.stringify(data)
});
if (!response.ok) throw new Error(‘Network response was not ok’);
const result = await response.json();
if (result.status !== 200) throw new Error(result.text || ‘API error’);
// 自动同步数据
this.syncData();
// 触发操作成功的回调
this.triggerCallbacks(operation, entity, data);
return result;
} catch (error) {
console.error(‘CRUD error:’, error);
// 触发操作失败的回调
this.triggerCallbacks(${operation}_error, entity, {
data,
error: error.message
});
throw error;
}
}
/**
执行CRUD操作
@param {string} operation - ‘add’, ‘delete’, ‘update’
@param {string} entity - 实体名称单数性质(小写)
@param {Object} data - 要发送的数据 后端要求数据格式为{属性: “值”, 关联对象: {id:0}, 关联对象集: [{id:0}]}
@returns {Promise} 响应结果
*/
async crudOperation(operation, entity, data) {
try {
const response = await fetch(${this.baseUrl}/app/${operation}/${entity}, {
method: ‘POST’,
headers: {‘Content-Type’: ‘application/json’},
body: JSON.stringify(data)
});
if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); // 自动同步数据 this.syncQueue = this.syncQueue.then(async () => { await this.syncData(); // 同步完成后触发操作回调 this.triggerCallbacks(operation, entity, data); }); return result;
} catch (error) {
console.error(‘CRUD error:’, error);
// 触发操作失败的回调
this.triggerCallbacks(${operation}_error, entity, {
data,
error: error.message
});
throw error;
}
}
/**
自动同步数据(防止频繁请求)
*/
async syncData() {
if (this.isSyncing) {
this.pendingSync = true;
return;
}
this.isSyncing = true;
try {
await this.fetchAll();
} catch (error) {
console.error(‘Sync failed:’, error);
} finally {
this.isSyncing = false;
// 处理等待中的同步请求 if (this.pendingSync) { this.pendingSync = false; setTimeout(() => this.syncData(), 1000); }
}
}
/**
添加实体
@param {string} entity - 实体名称单数性质
@param {Object} data - 实体数据
*/
async addEntity(entity, data) {
return this.crudOperation(‘add’, entity, data);
}
/**
更新实体
@param {string} entity - 实体名称单数性质
@param {Object} data - 实体数据(必须包含id)
*/
async updateEntity(entity, data) {
return this.crudOperation(‘update’, entity, data);
}
/**
删除实体
@param {string} entity - 实体名称单数性质
@param {number} id - 实体ID
*/
async deleteEntity(entity, id) {
return this.crudOperation(‘delete’, entity, {id});
}
/**
新增方法:手动触发数据刷新
*/
async refreshData() {
return this.syncQueue = this.syncQueue.then(() => this.syncData());
}
}
export { DataManager };
// 创建单例实例
//const dataManager = new DataManager(‘http://127.0.0.1:8080/KuCun2’);
//// 初始化时获取所有数据
//dataManager.fetchAll().then(() => {
// console.log(‘Initial data loaded’);
//});
// 导出数据对象,外部可以直接访问 data.bancais, data.dingdans 等
//export const data = dataManager.data;
//// 导出操作方法
//export const addEntity = dataManager.addEntity.bind(dataManager);
//export const updateEntity = dataManager.updateEntity.bind(dataManager);
//export const deleteEntity = dataManager.deleteEntity.bind(dataManager);
//export const fetchAll = dataManager.fetchAll.bind(dataManager);
------------------------ dingdan.js ------------------------
// 监听来自父窗口的消息
window.addEventListener(‘message’, function(event) {
if (event.source === window.parent && event.data === ‘DataManagerReady’) {
initializeDataManager();
}
});
// 初始化数据管理器
function initializeDataManager() {
const dataManager = window.parent.dataManager;
if (dataManager) { // 注册数据刷新回调 dataManager.registerCallback('all', function(operation, entity, data) { updatePageData(dataManager); }); // 初始页面数据更新 updatePageData(dataManager); // 设置搜索功能 setupSearch(dataManager); // 设置排序功能 setupSorting(); } else { console.error('DataManager not available'); }
}
// 更新页面数据
function updatePageData(dataManager) {
updateStats(dataManager);
updateTable(dataManager);
document.getElementById(‘lastUpdate’).textContent = new Date().toLocaleTimeString();
}
// 更新统计卡片数据
function updateStats(dataManager) {
const data = dataManager.data;
document.getElementById('orderCount').textContent = data.dingdans?.length || 0; document.getElementById('productCount').textContent = data.chanpins?.length || 0; document.getElementById('materialCount').textContent = data.bancais?.length || 0; const totalStock = data.kucuns?.reduce((sum, kucun) => sum + kucun.shuliang, 0) || 0; document.getElementById('totalStock').textContent = totalStock;
}
// 全局变量存储当前排序状态
let currentSort = {
column: null,
direction: ‘asc’ // ‘asc’ 或 ‘desc’
};
// 更新结果表格
function updateTable(dataManager) {
const tableBody = document.getElementById(‘resultBody’);
tableBody.innerHTML = ‘’;
const data = dataManager.data; let results = []; // 改为let以便排序 let resultCount = 0; // 处理订单产品数据 if (data.dingdan_chanpins) { data.dingdan_chanpins.forEach(dc => { if (!dc.dingdan || !dc.chanpin) return; if (dc.chanpin.chanpin_zujians) { dc.chanpin.chanpin_zujians.forEach(cz => { if (!cz.zujian || !cz.bancai) return; const bancai = cz.bancai; const materialInfo = getMaterialInfo(bancai); const stockQuantity = dataManager.data.kucuns?.find(ku => ku.bancai?.id==bancai.id)?.shuliang || 0; results.push({ orderNumber: dc.dingdan.number, productInfo: dc.chanpin.bianhao, productQuantity: dc.shuliang, component: cz.zujian.name, material: materialInfo, materialPerComponent: cz.one_howmany, materialOrderQuantity: dc.shuliang * cz.one_howmany, stockQuantity: stockQuantity, // 添加原始数据用于排序 raw: { orderNumber: dc.dingdan.number, productQuantity: dc.shuliang, materialPerComponent: cz.one_howmany, materialOrderQuantity: dc.shuliang * cz.one_howmany, stockQuantity: stockQuantity, thickness: bancai.houdu || 0 }, operation: `<button class="btn btn-sm btn-outline-primary" onclick="showMaterialDetail(${bancai.id})">详情</button>` }); resultCount++; }); } }); } // 处理直接订单组件数据 if (data.dingdan_chanpin_zujians) { data.dingdan_chanpin_zujians.forEach(dcz => { if (!dcz.dingdan || !dcz.chanpin_zujian || !dcz.chanpin_zujian.zujian || !dcz.bancai) return; const bancai = dcz.bancai; const materialInfo = getMaterialInfo(bancai); const stockQuantity = dataManager.data.kucuns?.find(ku => ku.bancai?.id==bancai.id)?.shuliang || 0; results.push({ orderNumber: dcz.dingdan.number, productInfo: dcz.chanpin_zujian.chanpin?.bianhao || '独立组件', productQuantity: dcz.shuliang, component: dcz.chanpin_zujian.zujian.name, material: materialInfo, materialPerComponent: dcz.chanpin_zujian.one_howmany, materialOrderQuantity: dcz.shuliang * dcz.chanpin_zujian.one_howmany, stockQuantity: stockQuantity, // 添加原始数据用于排序 raw: { orderNumber: dcz.dingdan.number, productQuantity: dcz.shuliang, materialPerComponent: dcz.chanpin_zujian.one_howmany, materialOrderQuantity: dcz.shuliang * dcz.chanpin_zujian.one_howmany, stockQuantity: stockQuantity, thickness: bancai.houdu || 0 }, operation: `<button class="btn btn-sm btn-outline-primary" onclick="showMaterialDetail(${bancai.id})">详情</button>` }); resultCount++; }); } // 应用排序 if (currentSort.column !== null) { results = sortResults(results, currentSort.column, currentSort.direction); } // 填充表格 if (resultCount > 0) { document.getElementById('noResults').style.display = 'none'; results.forEach(row => { const tr = document.createElement('tr'); tr.innerHTML = ` <td>${row.orderNumber}</td> <td>${row.productInfo}</td> <td>${row.productQuantity}</td> <td>${row.component}</td> <td>${row.material}</td> <td>${row.materialPerComponent}</td> <td>${row.materialOrderQuantity}</td> <td>${row.stockQuantity}</td> <td>${row.operation}</td> `; tableBody.appendChild(tr); }); } else { document.getElementById('noResults').style.display = 'flex'; } document.getElementById('resultCount').textContent = resultCount;
}
// 排序函数
function sortResults(results, columnIndex, direction) {
return results.sort((a, b) => {
// 根据列索引确定排序字段
let field;
switch(columnIndex) {
case 0: // 订单号
field = ‘orderNumber’;
break;
case 1: // 产品信息
field = ‘productInfo’;
break;
case 2: // 产品数量
field = ‘productQuantity’;
break;
case 3: // 组件
field = ‘component’;
break;
case 4: // 板材
// 特殊处理:按厚度排序
return sortByThickness(a, b, direction);
case 5: // 单件用量
field = ‘materialPerComponent’;
break;
case 6: // 订单用量
field = ‘materialOrderQuantity’;
break;
case 7: // 库存数量
field = ‘stockQuantity’;
break;
default:
return 0;
}
// 数值排序 if (['productQuantity', 'materialPerComponent', 'materialOrderQuantity', 'stockQuantity'].includes(field)) { return sortNumeric(a.raw[field], b.raw[field], direction); } // 字符串排序 return sortString(a[field], b[field], direction); });
}
// 按厚度排序
function sortByThickness(a, b, direction) {
return sortNumeric(a.raw.thickness, b.raw.thickness, direction);
}
// 数值排序
function sortNumeric(aVal, bVal, direction) {
const aNum = parseFloat(aVal) || 0;
const bNum = parseFloat(bVal) || 0;
if (direction === 'asc') { return aNum - bNum; } else { return bNum - aNum; }
}
// 字符串排序
function sortString(aVal, bVal, direction) {
const aStr = String(aVal).toLowerCase();
const bStr = String(bVal).toLowerCase();
if (aStr < bStr) { return direction === 'asc' ? -1 : 1; } else if (aStr > bStr) { return direction === 'asc' ? 1 : -1; } return 0;
}
// 获取板材详细信息函数(添加油状态)
function getMaterialInfo(bancai) {
if (!bancai) return ‘未知板材’;
// 获取材质名称 const caizhiName = bancai.caizhi?.name || '未知材质'; // 获取木皮信息(添加油状态) const formatMupi = (mupi) => { if (!mupi) return null; return `${mupi.name}${mupi.you ? '(油)' : ''}`; }; const mupi1Str = formatMupi(bancai.mupi1) || '无'; const mupi2Str = formatMupi(bancai.mupi2) || '无'; const mupiInfo = mupi1Str + (mupi2Str !== '无' ? `/${mupi2Str}` : ''); // 厚度转换为字符串 const thickness = bancai.houdu ? `${bancai.houdu.toFixed(1)}mm` : '未知厚度'; return `${caizhiName} - ${mupiInfo} (${thickness})`;
}
// 设置搜索功能(添加油状态搜索)
function setupSearch(dataManager) {
// 订单搜索
ParseError: KaTeX parse error: Expected 'EOF', got '#' at position 3: ('#̲orderSearch').o…(this).val().toLowerCase(), 0);
});
// 产品搜索 $('#productSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 1); }); // 板材材质搜索 $('#materialSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 4); }); // 木皮搜索(添加油状态搜索) $('#woodSearch').on('input', function() { const searchTerm = $(this).val().toLowerCase(); // 支持中文和数字搜索 const searchKeywords = { '有油': '有油', '无油': '无油', 'you': '有油', 'wu': '无油', '1': '有油', '0': '无油', '(油)': '(油)' }; const actualTerm = searchKeywords[searchTerm] || searchTerm; filterTable(actualTerm, 4); }); // 厚度搜索(修复正则表达式) $('#thicknessSearch').on('input', function() { filterTable($(this).val().toLowerCase(), 4); }); // 库存状态搜索 $('#stockStatusBtn').click(function() { const minStock = parseInt($('#minStock').val()) || 0; const maxStock = parseInt($('#maxStock').val()) || Number.MAX_SAFE_INTEGER; filterByStock(minStock, maxStock); });
}
// 设置排序功能
function setupSorting() {
// 获取所有表头
const headers = document.querySelectorAll(‘#resultsTable th[data-sortable]’);
headers.forEach((header, index) => { header.addEventListener('click', () => { // 更新排序状态 if (currentSort.column === index) { // 同一列:切换方向 currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc'; } else { // 新列:默认升序 currentSort.column = index; currentSort.direction = 'asc'; } // 更新UI updateSortIndicators(); // 重新渲染表格 const dataManager = window.parent.dataManager; if (dataManager) { updateTable(dataManager); } }); });
}
// 更新排序指示器
function updateSortIndicators() {
// 清除所有指示器
const headers = document.querySelectorAll(‘#resultsTable th[data-sortable]’);
headers.forEach(header => {
header.querySelector(‘.sort-indicator’).textContent = ‘’;
});
// 为当前排序列添加指示器 if (currentSort.column !== null) { const currentHeader = headers[currentSort.column]; const indicator = currentHeader.querySelector('.sort-indicator'); indicator.textContent = currentSort.direction === 'asc' ? '↑' : '↓'; }
}
// 表格过滤函数(修复厚度搜索)
function filterTable(searchTerm, columnIndex) {
const rows = $(‘#resultBody tr’);
let visibleCount = 0;
rows.each(function() { const cellText = $(this).find(`td:eq(${columnIndex})`).text().toLowerCase(); let isMatch = false; // 特殊处理油状态搜索 if (searchTerm === '有油' || searchTerm === '无油' || searchTerm === '(油)') { isMatch = cellText.includes(searchTerm); } // 处理厚度字符串匹配(修复正则表达式) else if (columnIndex === 4 && !isNaN(parseFloat(searchTerm))) { // 提取厚度数字部分进行匹配 const thicknessMatch = cellText.match(/(\d+\.?\d*)/); if (thicknessMatch) { const thicknessValue = parseFloat(thicknessMatch[1]); const searchValue = parseFloat(searchTerm); // 允许小数点误差 isMatch = Math.abs(thicknessValue - searchValue) < 0.5; } } // 常规文本匹配 else { isMatch = cellText.includes(searchTerm); } $(this).toggle(isMatch); if (isMatch && searchTerm) { $(this).addClass('highlight'); } else { $(this).removeClass('highlight'); } if (isMatch) visibleCount++; }); document.getElementById('resultCount').textContent = visibleCount; document.getElementById('noResults').style.display = visibleCount > 0 ? 'none' : 'flex';
}
// 按库存量过滤
function filterByStock(minStock, maxStock) {
const rows = $(‘#resultBody tr’);
let visibleCount = 0;
rows.each(function() { const stockCell = $(this).find('td:eq(7)').text(); const stockValue = parseInt(stockCell) || 0; const isMatch = stockValue >= minStock && stockValue <= maxStock; $(this).toggle(isMatch); if (isMatch) visibleCount++; }); document.getElementById('resultCount').textContent = visibleCount; document.getElementById('noResults').style.display = visibleCount > 0 ? 'none' : 'flex';
}
// 显示板材详情(添加油状态显示)
function showMaterialDetail(bancaiId) {
const dataManager = window.parent.dataManager;
if (!dataManager) return;
const bancais = dataManager.data.bancais || []; const bancai = bancais.find(b => b.id === bancaiId); const kucun = dataManager.data.kucuns?.fill(ku => ku.bancai.id==bancai.id) ; if (!bancai) { alert('未找到板材信息'); return; } // 格式化木皮信息(添加油状态) const formatMupiDetail = (mupi) => { if (!mupi) return '无'; return `${mupi.name} ${mupi.you ? '(油)' : ''}`; }; // 构建详情信息 const detailHtml = ` <div class="material-detail"> <h4>板材详情 (ID: ${bancai.id})</h4> <p><strong>材质:</strong> ${bancai.caizhi?.name || '未知'}</p> <p><strong>厚度:</strong> ${bancai.houdu ? bancai.houdu.toFixed(1) + 'mm' : '未知'}</p> <p><strong>木皮1:</strong> ${formatMupiDetail(bancai.mupi1)}</p> <p><strong>木皮2:</strong> ${formatMupiDetail(bancai.mupi2)}</p> <p><strong>库存数量:</strong> ${kucun?.shuliang || 0}</p> <div class="related-orders"> <h5>相关订单:</h5> <ul> ${getRelatedOrders(bancai).map(order => `<li>订单 ${order.number} (ID: ${order.id})</li>` ).join('') || '<li>无相关订单</li>'} </ul> </div> </div> `; // 显示详情(实际项目中可用模态框) const detailWindow = window.open('', '_blank', 'width=600,height=400'); detailWindow.document.write(` <!DOCTYPE html> <html> <head> <title>板材详情</title> <style> body { font-family: Arial, sans-serif; padding: 20px; } .material-detail { max-width: 500px; } h4 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; } p { margin: 10px 0; } .related-orders { margin-top: 20px; } ul { list-style-type: none; padding: 0; } li { padding: 5px 0; border-bottom: 1px solid #eee; } </style> </head> <body> ${detailHtml} </body> </html> `); detailWindow.document.close();
}
// 获取板材相关订单
function getRelatedOrders(bancai) {
const dataManager = window.parent.dataManager;
if (!dataManager) return [];
const orders = []; const dingdan_chanpin_zujians = dataManager.data.dingdan_chanpin_zujians || []; // 查找直接订单组件关联 dingdan_chanpin_zujians.forEach(dcz => { if (dcz.bancai?.id === bancai.id && dcz.dingdan && !orders.some(o => o.id === dcz.dingdan.id)) { orders.push(dcz.dingdan); } }); // 查找产品组件关联 const chanpin_zujians = dataManager.data.chanpin_zujians || []; chanpin_zujians.forEach(cz => { if (cz.bancai?.id === bancai.id) { const dingdan_chanpins = dataManager.data.dingdan_chanpins || []; dingdan_chanpins.forEach(dc => { if (dc.chanpin?.id === cz.chanpin?.id && dc.dingdan && !orders.some(o => o.id === dc.dingdan.id)) { orders.push(dc.dingdan); } }); } }); return orders;
}
// 页面加载时尝试初始化
if (window.parent) {
window.parent.postMessage(‘RequestDataManager’, ‘*’);
}
// 添加全局函数供按钮调用
window.showMaterialDetail = showMaterialDetail;
------------------------ test.html ------------------------
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>板材库存查询系统</title> <!-- 引入外部CSS --> <link rel="stylesheet" href="../css/dingdan.css"> <!-- 引入jQuery --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <!-- 引入Bootstrap --> <link href="../js/bootstrap-5.3.0-alpha1-dist/css/bootstrap.min.css" rel="stylesheet"> <script src="../js/bootstrap-5.3.0-alpha1-dist/umd/popper.min.js"></script> <script src="../js/bootstrap-5.3.0-alpha1-dist/js/bootstrap.min.js"></script> <!-- 引入Bootstrap Icons --> <link rel="stylesheet" href="../js/bootstrap-icons-1.8.1/bootstrap-icons.css"> <!-- 引入主JS文件 --> <script src="../js/main.js"></script> </head> <body> <div class="container py-4"> <!-- 标题部分 --> <div class="text-center mb-4"> <h1 class="text-primary"><i class="bi bi-boxes"></i> 板材库存管理系统</h1> <p class="text-muted">查询订单、产品、板材及库存信息</p> </div> <!-- 统计卡片 --> <div class="row mb-4"> <div class="col-md-3"> <div class="card stats-card border-primary"> <div class="card-body"> <h5 class="card-title">订单总数</h5> <p class="card-text fs-3 text-primary" id="orderCount">0</p> </div> </div> </div> <div class="col-md-3"> <div class="card stats-card border-info"> <div class="card-body"> <h5 class="card-title">产品种类</h5> <p class="card-text fs-3 text-info" id="productCount">0</p> </div> </div> </div> <div class="col-md-3"> <div class="card stats-card border-success"> <div class="card-body"> <h5 class="card-title">板材库存</h5> <p class="card-text fs-3 text-success" id="materialCount">0</p> </div> </div> </div> <div class="col-md-3"> <div class="card stats-card border-warning"> <div class="card-body"> <h5 class="card-title">库存总量</h5> <p class="card-text fs-3 text-warning" id="totalStock">0</p> </div> </div> </div> </div> <!-- 搜索区域 --> <div class="card search-section mb-4"> <div class="card-header"> <h5 class="mb-0"><i class="bi bi-search me-2"></i>高级搜索</h5> </div> <div class="card-body"> <div class="row g-3"> <!-- 订单搜索 --> <div class="col-md-4"> <div class="search-control"> <i class="bi bi-clipboard-search search-icon"></i> <input type="text" class="form-control with-icon" id="orderSearch" placeholder="搜索订单号..." aria-label="订单号搜索"> </div> </div> <!-- 产品搜索 --> <div class="col-md-4"> <div class="search-control"> <i class="bi bi-grid search-icon"></i> <input type="text" class="form-control with-icon" id="productSearch" placeholder="搜索产品编号..." aria-label="产品编号搜索"> </div> </div> <!-- 板材搜索 --> <div class="col-md-4"> <div class="search-control"> <i class="bi bi-box search-icon"></i> <input type="text" class="form-control with-icon" id="materialSearch" placeholder="搜索板材ID或材质..." aria-label="板材搜索"> </div> </div> <!-- 木皮搜索 --> <div class="col-md-4"> <div class="search-control"> <i class="bi bi-tree search-icon"></i> <input type="text" class="form-control with-icon" id="woodSearch" placeholder="搜索木皮名称..." aria-label="木皮搜索"> </div> </div> <!-- 厚度搜索 --> <div class="col-md-4"> <div class="search-control"> <i class="bi bi-arrows-vertical search-icon"></i> <input type="number" class="form-control with-icon" id="thicknessSearch" placeholder="厚度(mm)" min="0" step="0.1"> </div> </div> <!-- 库存范围搜索 --> <div class="col-md-4"> <div class="input-group"> <span class="input-group-text"><i class="bi bi-box"></i></span> <input type="number" class="form-control" id="minStock" placeholder="最小库存" min="0"> <input type="number" class="form-control" id="maxStock" placeholder="最大库存" min="0"> <button class="btn btn-primary" type="button" id="stockStatusBtn"> <i class="bi bi-search"></i> </button> </div> </div> </div> </div> </div> <!-- 结果区域 --> <div class="card"> <div class="card-header d-flex justify-content-between align-items-center"> <h5 class="mb-0"><i class="bi bi-table me-2"></i>查询结果</h5> <div class="text-secondary"> <span id="resultCount">0</span> 条记录 <span class="ms-2"><i class="bi bi-info-circle"></i> <small>实时数据更新时间: <span id="lastUpdate">--:--:--</span></small></span> </div> </div> <div class="card-body result-section"> <div class="table-responsive"> <table class="table table-hover" id="resultsTable"> <thead class="table-light sticky-top"> <tr> <th data-sortable>订单号 <span class="sort-indicator"></span></th> <th data-sortable>产品信息 <span class="sort-indicator"></span></th> <th data-sortable>产品数量 <span class="sort-indicator"></span></th> <th data-sortable>组件 <span class="sort-indicator"></span></th> <th data-sortable>板材 <span class="sort-indicator"></span></th> <th data-sortable>单件用量 <span class="sort-indicator"></span></th> <th data-sortable>订单用量 <span class="sort-indicator"></span></th> <th data-sortable>库存数量 <span class="sort-indicator"></span></th> <th>操作</th> </tr> </thead> <tbody id="resultBody"> <!-- 数据加载中 --> <tr id="loadingRow"> <td colspan="9" class="text-center py-5"> <div class="d-flex align-items-center justify-content-center"> <div class="spinner-border text-primary" role="status"> <span class="visually-hidden">加载中...</span> </div> <div class="ms-3">正在加载数据,请稍候...</div> </div> </td> </tr> </tbody> </table> </div> <!-- 空结果提示 --> <div id="noResults" class="no-results text-center py-5" style="display: none;"> <div> <i class="bi bi-inboxes text-muted" style="font-size: 3rem;"></i> <h4 class="mt-3 text-muted">没有找到匹配的记录</h4> <p class="text-muted">请尝试调整您的搜索条件</p> </div> </div> </div> </div> </div> <!-- 引入订单JS --> <script src="../js/dingdan.js"></script> </body> </html> 改造页面逻辑,已经删除了dingdan_chanpin_zujian,java和DataManager.js.js是不能改 要求 一个订单有很多产品不同数量,每个产品可以再很多订单中,一个产品有很多组件,一个组件可以在很多产品中,因为每个组件因为在不同的产品中有不同的生产工艺,所以使用不同的板材和板材能生产组件数量,每个板材有不同的材质和两面木皮,木皮表面可能有油漆, 订购时可能直接购入板材,也可能按订单和产品订购板材,也用可能按订单产品组件订购板材,每次采购不标准,一个订单可能订购几次,用户有姓名 账号 密码 权限, 一个记录进货和消耗,查看的时候会查看订单下有多少板材可用