黄伟杰 2 months ago
commit 28123d2457

@ -0,0 +1,55 @@
import request from '@/config/axios'
// 节假日设置 VO
export interface CalHolidayVO {
holidayId: number // 流水号
theDay: Date // 日期
holidayType: string // 日期类型
startTime: Date // 开始时间
endTime: Date // 结束时间
remark: string // 备注
attr1: string // 预留字段1
attr2: string // 预留字段2
attr3: number // 预留字段3
attr4: number // 预留字段4
createBy: string // 创建者
updateBy: string // 更新者
}
// 节假日设置 API
export const CalHolidayApi = {
// 查询节假日设置分页
getCalHolidayPage: async (params: any) => {
return await request.get({ url: `/mes/cal-holiday/page`, params })
},
// 查询节假日设置详情
getCalHoliday: async (id: number) => {
return await request.get({ url: `/mes/cal-holiday/get?id=` + id })
},
// 新增节假日设置
createCalHoliday: async (data: CalHolidayVO) => {
return await request.post({ url: `/mes/cal-holiday/create`, data })
},
// 修改节假日设置
updateCalHoliday: async (data: CalHolidayVO) => {
return await request.put({ url: `/mes/cal-holiday/update`, data })
},
// 删除节假日设置
deleteCalHoliday: async (id: number) => {
return await request.delete({ url: `/mes/cal-holiday/delete?id=` + id })
},
// 导出节假日设置 Excel
exportCalHoliday: async (params) => {
return await request.download({ url: `/mes/cal-holiday/export-excel`, params })
},
// 删除节假日设置
deleteCalHolidayByDay: async (theDay: String) => {
return await request.delete({ url: `/mes/cal-holiday/deleteByDay?theDay=` + theDay })
},
}

@ -0,0 +1,85 @@
import request from '@/config/axios'
// esop文件表库 VO
export interface FileVO {
id: number // id
configId: number // 配置编号
code: string // 文件编码
name: string // 文件名
path: string // 文件路径
url: string // 文件 URL
type: string // 文件类型
class: string // 文件分类
status: number // 文件状态
size: number // 文件大小
}
// 文件预签名地址 Response VO
export interface FilePresignedUrlRespVO {
// 文件配置编号
configId: number
// 文件上传 URL
uploadUrl: string
// 文件 URL
url: string
}
export enum ApiUrl{
'/admin-api/mes/esop/file/create'
}
// esop文件表库 API
export const FileApi = {
// 查询esop文件表库分页
getFilePage: async (params: any) => {
return await request.get({ url: `/esop/file/page`, params })
},
// 查询esop文件表库详情
getFile: async (id: number) => {
return await request.get({ url: `/esop/file/get?id=` + id })
},
// 新增esop文件表库
createFile: async (data: FileVO) => {
return await request.post({ url: `/esop/file/create`, data })
},
// 修改esop文件表库
updateFile: async (data: FileVO) => {
return await request.put({ url: `/esop/file/update`, data })
},
// 删除esop文件表库
deleteFile: async (id: number) => {
return await request.delete({ url: `/esop/file/delete?id=` + id })
},
// 导出esop文件表库 Excel
exportFile: async (params) => {
return await request.download({ url: `/esop/file/export-excel`, params })
},
// 获取文件编码
generateCode: async () => {
return await request.get({ url: `/esop/file/generate`})
},
}
// 获取文件预签名地址
export const getFilePresignedUrl = (path: string) => {
return request.get<FilePresignedUrlRespVO>({
url: '/infra/file/presigned-url',
params: { path }
})
}
// 创建文件
export const createFile = (data: any) => {
return request.post({ url: '/esop/file/create', data })
}
// 上传文件
export const updateFile = (data: any) => {
return request.upload({ url: '/esop/file/create', data })
}

@ -542,6 +542,43 @@ export default {
large: 'Large', large: 'Large',
small: 'Small' small: 'Small'
}, },
home:{
welcome: 'Welcome to use the Bishuo Digital Intelligent Central Control Platform',
message: 'The Bishuo Digital Intelligent Central Control Platform takes production operation as the core, uniformly integrating key business modules such as production planning, data collection, warehousing, equipment, energy, molds, quality, formulas and report analysis, to achieve full-process digital management from planning to execution, from equipment to products, and from data to decision-making.',
productTitle:'Overall production overview',
placeholderCreateTimeStart: 'Start Date',
placeholderCreateTimeEnd: 'End Date',
productionSchedule:'Real-time production progress',
productionPlan:'Production plan',
productionName:'Production name',
planNumber:'Plan quantity',
productionLine:'Production line',
planStartTime:'Plan start time',
planEndTime:'Plan end time',
completedQuantity:'Completed quantity',
qualifiedQuantity:'Qualified quantity',
unqualifiedQuantity:'Unqualified quantity',
yieldRate: 'YIELD',
actualEndTime:'Actual end time',
gtasks: 'Gtask',
missionNumber:'Mission number',
taskType:'Task type',
target:'Target',
creationTime:'Creation time',
equipment:'Equipment',
mould:'Mould',
equipmentTile:'Overall condition of the collection equipment',
equipmentCount:'Total equipment count',
operation:'Operation',
standbyMode:'Standby mode',
malfunction:'During the malfunction',
alerting:'Alerting...',
useRatio:'use ratio',
failureRate:'failure rate',
equipmentTitle:'Statistics of equipment maintenance quantities',
equipmentClass:'Equipment classification statistics',
equipmentMessage:'Classify and count by mold type, and select the top 10 items with the largest number of molds.',
},
login: { login: {
welcome: 'Welcome to the system', welcome: 'Welcome to the system',
message: 'Backstage management system', message: 'Backstage management system',
@ -892,6 +929,7 @@ export default {
SystemManagement: { SystemManagement: {
Dept: { Dept: {
name: 'Department Name', name: 'Department Name',
enName: 'Department Name (en)',
statusLabel: 'Department Status', statusLabel: 'Department Status',
status: 'Status', status: 'Status',
leader: 'Leader', leader: 'Leader',
@ -1079,6 +1117,7 @@ export default {
Dict: { Dict: {
id: 'Dict ID', id: 'Dict ID',
name: 'Dict Name', name: 'Dict Name',
enName: 'Dict Name (en)',
type: 'Dict Type', type: 'Dict Type',
label: 'Dict Label', label: 'Dict Label',
labelEn: 'Dict Label (EN)', labelEn: 'Dict Label (EN)',
@ -1097,6 +1136,7 @@ export default {
searchLabelPlaceholder: 'Please input dict label', searchLabelPlaceholder: 'Please input dict label',
searchDataStatusPlaceholder: 'Please select data status', searchDataStatusPlaceholder: 'Please select data status',
namePlaceholder: 'Please input dict name', namePlaceholder: 'Please input dict name',
enNamePlaceholder: 'Please input dict name (en)',
typePlaceholder: 'Please input dict type', typePlaceholder: 'Please input dict type',
labelPlaceholder: 'Please input data label', labelPlaceholder: 'Please input data label',
labelEnPlaceholder: 'Please input data label (EN)', labelEnPlaceholder: 'Please input data label (EN)',
@ -2069,6 +2109,69 @@ export default {
validatorNameRequired: 'Unit name can not be empty', validatorNameRequired: 'Unit name can not be empty',
validatorStatusRequired: 'Unit status can not be empty', validatorStatusRequired: 'Unit status can not be empty',
validatorPrimaryFlagRequired: 'Primary unit flag can not be empty' validatorPrimaryFlagRequired: 'Primary unit flag can not be empty'
},
CalHoliday: {
setWorkingDays: 'set working days',
setHoliday: 'set holiday',
lastMonth:'last month',
today:'today',
nextMonth:'next month',
work:'work',
rest:'rest',
searchDateStartPlaceholder: '开始日期',
searchDateEndPlaceholder: '结束日期',
searchTypeLabel: '类型',
searchTypePlaceholder: '请选择类型',
searchRemarkLabel: '备注',
searchRemarkPlaceholder: '请输入备注',
searchButtonText: '搜索',
resetButtonText: '重置',
addButtonText: '新增',
exportButtonText: '导出'
},
EsopFile: {
moduleName: 'File Management',
searchCodeLabel: 'File Code',
searchCodePlaceholder: 'Please enter file code',
searchFileNameLabel: 'File_Name',
searchFileNamePlaceholder: 'Please enter file name',
searchClassificationLabel: 'File Classification',
searchClassificationPlaceholder: 'Please select file Classification',
searchStatusLabel: 'File Status',
searchStatusPlaceholder: 'Please select file status',
searchButtonText: 'Search',
resetButtonText: 'Reset',
uploadButtonText: 'Upload',
exportButtonText: 'Export',
tableCodeColumn: 'File Code',
tableNameColumn: 'File Name',
tableClassificationColumn: 'File Classification',
tableTypeColumn: 'File Type',
tableStatusColumn: 'File Status',
tableCreatorNameColumn: 'Uploader',
tableCreateTimeColumn: 'Upload Time',
tableOperateColumn: 'Operation',
tableEditAction: 'Edit',
tableDownloadAction: 'Download',
tableDeleteAction: 'Delete',
dialogFileNameLabel: 'File Name',
dialogFileNamePlaceholder: 'Please enter file name',
dialogClassificationLabel: 'File Classification',
dialogClassificationPlaceholder: 'Please select file classification',
dialogStatusLabel: 'File Status',
dialogCancelButton: 'Cancel',
dialogSubmitButton: 'Confirm',
messageOne: 'Tip: Only ',
messageTwo: ' format files are allowed to be imported!',
messageThree: ' Drag the file to this area, or ',
messageFour: ' click to upload',
validatorCodeRequired: 'File code can not be empty',
validatorNameRequired: 'File name can not be empty',
validatorClassificationRequired: 'File classification can not be empty',
validatorTypeRequired: 'File type can not be empty',
validatorStatusRequired: 'File status can not be empty'
} }
}, },

@ -543,6 +543,43 @@ export default {
large: '大', large: '大',
small: '小' small: '小'
}, },
home: {
welcome: '欢迎您使用必硕数字化智能中控平台',
message: '必硕数字化智能中控平台以生产运营为核心,统一整合生产计划、数据采集、仓储、设备、能源、模具、质量、配方及报表分析等关键业务模块,实现从计划到执行、从设备到制品、从数据到决策的全流程数字化管理。',
productTitle: '整体生产概况',
placeholderCreateTimeStart: '开始日期',
placeholderCreateTimeEnd: '结束日期',
productionSchedule:'实时生产进度',
productionPlan:'生产计划',
productionName:'生产名称',
planNumber:'计划数量',
productionLine:'生产线',
planStartTime:'计划开始时间',
planEndTime:'计划结束时间',
completedQuantity:'完工数量',
qualifiedQuantity:'合格数量',
unqualifiedQuantity:'不合格数量',
yieldRate:'合格率',
actualEndTime:'实际结束时间',
gtasks:'待办任务',
missionNumber:'任务编号',
taskType:'任务类型',
target:'任务目标',
creationTime:'创建时间',
equipment:'设备',
mould:'模具',
equipmentTile:'采集设备整体情况',
equipmentCount:'设备总数',
operation:'运行',
standbyMode:'待机',
malfunction:'故障中',
alerting:'报警中',
useRatio:'利用率',
failureRate:'故障率',
equipmentTitle:'设备维修数量统计',
equipmentClass:'设备分类统计',
equipmentMessage:'按模具分类统计取模具数量最多的前10项'
},
login: { login: {
welcome: '欢迎使用必硕数字化智能中控平台', welcome: '欢迎使用必硕数字化智能中控平台',
message: '必硕智能“纸”为绿色生活', message: '必硕智能“纸”为绿色生活',
@ -1079,6 +1116,7 @@ export default {
Dict: { Dict: {
id: '字典编号', id: '字典编号',
name: '字典名称', name: '字典名称',
enName: '字典英文名称',
type: '字典类型', type: '字典类型',
label: '字典标签', label: '字典标签',
labelEn: '字典标签(英文)', labelEn: '字典标签(英文)',
@ -1097,6 +1135,7 @@ export default {
searchLabelPlaceholder: '请输入字典标签', searchLabelPlaceholder: '请输入字典标签',
searchDataStatusPlaceholder: '请选择数据状态', searchDataStatusPlaceholder: '请选择数据状态',
namePlaceholder: '请输入字典名称', namePlaceholder: '请输入字典名称',
enNamePlaceholder: '请输入字典英文名称',
typePlaceholder: '请输入字典类型', typePlaceholder: '请输入字典类型',
labelPlaceholder: '请输入数据标签', labelPlaceholder: '请输入数据标签',
labelEnPlaceholder: '请输入数据标签(英文)', labelEnPlaceholder: '请输入数据标签(英文)',
@ -2875,7 +2914,66 @@ export default {
validatorNameRequired: '单位名称不能为空', validatorNameRequired: '单位名称不能为空',
validatorStatusRequired: '单位状态不能为空', validatorStatusRequired: '单位状态不能为空',
validatorPrimaryFlagRequired: '是否主单位不能为空' validatorPrimaryFlagRequired: '是否主单位不能为空'
},
//假日管理
CalHoliday: {
setWorkingDays: '设置工作日',
setHoliday: '设置休息日',
lastMonth:'上个月',
today:'今天',
nextMonth:'下个月',
work:'班',
rest:'休',
searchDateStartPlaceholder: '开始日期',
searchDateEndPlaceholder: '结束日期',
searchTypeLabel: '类型',
searchTypePlaceholder: '请选择类型',
searchRemarkLabel: '备注',
searchRemarkPlaceholder: '请输入备注',
searchButtonText: '搜索',
resetButtonText: '重置',
addButtonText: '新增',
exportButtonText: '导出'
},
//esop文件管理
EsopFile: {
searchFileNameLabel: '文件名称',
searchFileNamePlaceholder: '请输入文件名',
searchClassificationLabel: '文件分类',
searchClassificationPlaceholder: '请选择文件分类',
searchStatusLabel: '文件状态',
searchStatusPlaceholder: '请选择文件状态',
searchButtonText: '搜索',
resetButtonText: '重置',
uploadButtonText: '文件上传',
addButtonText: '新增',
exportButtonText: '导出',
tableCodeColumn:'文件编码',
tableNameColumn: '文件名称',
tableClassificationColumn: '文件分类',
tableTypeColumn: '文件类型',
tableStatusColumn: '文件状态',
tableCreatorNameColumn: '上传人',
tableCreateTimeColumn: '上传时间',
tableOperateColumn: '操作',
tableEditAction: '编辑',
tableDownloadAction:'下载',
tableDeleteAction: '删除',
dialogFileNameLabel: '文件名',
dialogFileNamePlaceholder: '请输入文件名',
dialogClassificationLabel: '文件分类',
dialogClassificationPlaceholder: '请选择文件分类',
dialogStatusLabel: '文件状态',
dialogCancelButton: '取 消',
dialogSubmitButton: '确 定',
messageOne:'提示:仅允许导入 ',
messageTwo:' 格式文件!',
messageThree:' 将文件拖到此处,或',
messageFour:'点击上传',
validatorNameRequired: '文件名不能为空',
validatorStatusRequired: '文件状态不能为空'
} }
}, },
ProductionPlan: { ProductionPlan: {
Task: { Task: {
@ -4221,6 +4319,8 @@ export default {
messageDeviceNoParams: '该设备下没有参数', messageDeviceNoParams: '该设备下没有参数',
messageFetchChartFailed: '获取图表数据失败' messageFetchChartFailed: '获取图表数据失败'
} }
} }
} }
} }

@ -0,0 +1,668 @@
/**
* @1900-2100区间内的公历农历互转
* @charset UTF-8
* @Author Jea杨(JJonline@JJonline.Cn)
* @Time 2014-7-21
* @Time 2016-8-13 Fixed 2033hexAttribution Annals
* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
* @Version 1.0.3
* @公历转农历calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
* @农历转公历calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
*/
const calendar = {
/**
* 农历1900-2100的润大小信息表
* @Array Of Property
* @return Hex
*/
lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,//1900-1909
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,//1910-1919
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,//1920-1929
0x06566, 0x0d4a0, 0x0ea50, 0x16a95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,//1930-1939
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,//1940-1949
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0,//1950-1959
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,//1960-1969
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6,//1970-1979
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,//1980-1989
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0,//1990-1999
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,//2000-2009
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,//2010-2019
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,//2020-2029
0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,//2030-2039
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0,//2040-2049
/**Add By JJonline@JJonline.Cn**/
0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0,//2050-2059
0x092e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4,//2060-2069
0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0,//2070-2079
0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160,//2080-2089
0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252,//2090-2099
0x0d520],//2100
/**
* 公历每个月份的天数普通表
* @Array Of Property
* @return Number
*/
solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
/**
* 天干地支之天干速查表
* @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
* @return Cn string
*/
Gan: ["\u7532", "\u4e59", "\u4e19", "\u4e01", "\u620a", "\u5df1", "\u5e9a", "\u8f9b", "\u58ec", "\u7678"],
/**
* 天干地支之地支速查表
* @Array Of Property
* @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
* @return Cn string
*/
Zhi: ["\u5b50", "\u4e11", "\u5bc5", "\u536f", "\u8fb0", "\u5df3", "\u5348", "\u672a", "\u7533", "\u9149", "\u620c", "\u4ea5"],
/**
* 天干地支之地支速查表<=>生肖
* @Array Of Property
* @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
* @return Cn string
*/
Animals: ["\u9f20", "\u725b", "\u864e", "\u5154", "\u9f99", "\u86c7", "\u9a6c", "\u7f8a", "\u7334", "\u9e21", "\u72d7", "\u732a"],
/**
* 阳历节日
*/
festival: {
'1-1': {title: '元旦节'},
'2-14': {title: '情人节'},
'5-1': {title: '劳动节'},
'5-4': {title: '青年节'},
'6-1': {title: '儿童节'},
'9-10': {title: '教师节'},
'10-1': {title: '国庆节'},
'12-25': {title: '圣诞节'},
'3-8': {title: '妇女节'},
'3-12': {title: '植树节'},
'4-1': {title: '愚人节'},
'5-12': {title: '护士节'},
'7-1': {title: '建党节'},
'8-1': {title: '建军节'},
'12-24': {title: '平安夜'},
},
/**
* 农历节日
*/
lFestival: {
'12-30': {title: '除夕'},
'1-1': {title: '春节'},
'1-15': {title: '元宵节'},
'2-2': {title: '龙抬头'},
'5-5': {title: '端午节'},
'7-7': {title: '七夕节'},
'7-15': {title: '中元节'},
'8-15': {title: '中秋节'},
'9-9': {title: '重阳节'},
'10-1': {title: '寒衣节'},
'10-15': {title: '下元节'},
'12-8': {title: '腊八节'},
'12-23': {title: '北方小年'},
'12-24': {title: '南方小年'},
},
/**
* 返回默认定义的阳历节日
*/
getFestival() {
return this.festival
},
/**
* 返回默认定义的内容里节日
*/
getLunarFestival() {
return this.lFestival
},
/**
*
* @param param {Object} 按照festival的格式输入数据设置阳历节日
*/
setFestival(param = {}) {
this.festival = param
},
/**
*
* @param param {Object} 按照lFestival的格式输入数据设置农历节日
*/
setLunarFestival(param = {}) {
this.lFestival = param
},
/**
* 24节气速查表
* @Array Of Property
* @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
* @return Cn string
*/
solarTerm: ["\u5c0f\u5bd2", "\u5927\u5bd2", "\u7acb\u6625", "\u96e8\u6c34", "\u60ca\u86f0", "\u6625\u5206", "\u6e05\u660e", "\u8c37\u96e8", "\u7acb\u590f", "\u5c0f\u6ee1", "\u8292\u79cd", "\u590f\u81f3", "\u5c0f\u6691", "\u5927\u6691", "\u7acb\u79cb", "\u5904\u6691", "\u767d\u9732", "\u79cb\u5206", "\u5bd2\u9732", "\u971c\u964d", "\u7acb\u51ac", "\u5c0f\u96ea", "\u5927\u96ea", "\u51ac\u81f3"],
/**
* 1900-2100各年的24节气日期速查表
* @Array Of Property
* @return 0x string For splice
*/
sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
'97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
'97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
'97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
'97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
'97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
'9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
'97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
'97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
'7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
'97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
'977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
'7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
'7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
'665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'],
/**
* 数字转中文速查表
* @Array Of Property
* @trans ['日','一','二','三','四','五','六','七','八','九','十']
* @return Cn string
*/
nStr1: ["\u65e5", "\u4e00", "\u4e8c", "\u4e09", "\u56db", "\u4e94", "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341"],
/**
* 日期转农历称呼速查表
* @Array Of Property
* @trans ['初','十','廿','卅']
* @return Cn string
*/
nStr2: ["\u521d", "\u5341", "\u5eff", "\u5345"],
/**
* 月份转农历称呼速查表
* @Array Of Property
* @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
* @return Cn string
*/
nStr3: ["\u6b63", "\u4e8c", "\u4e09", "\u56db", "\u4e94", "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341", "\u51ac", "\u814a"],
/**
* 返回农历y年一整年的总天数
* @param y lunar Year
* @return Number
* @eg:var count = calendar.lYearDays(1987) ;//count=387
*/
lYearDays: function (y) {
let i, sum = 348;
for (i = 0x8000; i > 0x8; i >>= 1) {
sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0;
}
return (sum + this.leapDays(y));
},
/**
* 返回农历y年闰月是哪个月若y年没有闰月 则返回0
* @param y lunar Year
* @return Number (0-12)
* @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
*/
leapMonth: function (y) { //闰字编码 \u95f0
return (this.lunarInfo[y - 1900] & 0xf);
},
/**
* 返回农历y年闰月的天数 若该年没有闰月则返回0
* @param y lunar Year
* @return Number (02930)
* @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
*/
leapDays: function (y) {
if (this.leapMonth(y)) {
return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29);
}
return (0);
},
/**
* 返回农历y年m月非闰月的总天数计算m为闰月时的天数请使用leapDays方法
* @param y lunar Year
* @param m lunar Month
* @return Number (-12930)
* @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
*/
monthDays: function (y, m) {
if (m > 12 || m < 1) {
return -1
}//月份参数从1至12参数错误返回-1
return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29);
},
/**
* 返回公历(!)y年m月的天数
* @param y solar Year
* @param m solar Month
* @return Number (-128293031)
* @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
*/
solarDays: function (y, m) {
if (m > 12 || m < 1) {
return -1
} //若参数错误 返回-1
const ms = m - 1;
if (ms === 1) { //2月份的闰平规律测算后确认返回28或29
return (((y % 4 === 0) && (y % 100 !== 0) || (y % 400 === 0)) ? 29 : 28);
} else {
return (this.solarMonth[ms]);
}
},
/**
* 农历年份转换为干支纪年
* @param lYear 农历年的年份数
* @return Cn string
*/
toGanZhiYear: function (lYear) {
var ganKey = (lYear - 3) % 10;
var zhiKey = (lYear - 3) % 12;
if (ganKey === 0) ganKey = 10;//如果余数为0则为最后一个天干
if (zhiKey === 0) zhiKey = 12;//如果余数为0则为最后一个地支
return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1];
},
/**
* 公历月日判断所属星座
* @param cMonth [description]
* @param cDay [description]
* @return Cn string
*/
toAstro: function (cMonth, cDay) {
const s = "\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf";
const arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22];
return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + "\u5ea7";//座
},
/**
* 传入offset偏移量返回干支
* @param offset 相对甲子的偏移量
* @return Cn string
*/
toGanZhi: function (offset) {
return this.Gan[offset % 10] + this.Zhi[offset % 12];
},
/**
* 传入公历(!)y年获得该年第n个节气的公历日期
* @param y y公历年(1900-2100)
* @param n n二十四节气中的第几个节气(1~24)从n=1(小寒)算起
* @return day Number
* @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
*/
getTerm: function (y, n) {
if( y < 1900 || y > 2100 || n < 1 || n > 24) {
return -1;
}
const _table = this.sTermInfo[y - 1900];
const _calcDay = []
for (let index = 0; index < _table.length; index += 5) {
const chunk = parseInt('0x' + _table.substr(index, 5)).toString()
_calcDay.push(
chunk[0],
chunk.substr(1, 2),
chunk[3],
chunk.substr(4, 2)
)
}
return parseInt(_calcDay[n - 1]);
},
/**
* 传入农历数字月份返回汉语通俗表示法
* @param m lunar month
* @return Cn string
* @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
*/
toChinaMonth: function (m) { // 月 => \u6708
if (m > 12 || m < 1) {
return -1
} //若参数错误 返回-1
let s = this.nStr3[m - 1];
s += "\u6708";//加上月字
return s;
},
/**
* 传入农历日期数字返回汉字表示法
* @param d lunar day
* @return Cn string
* @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
*/
toChinaDay: function (d) { //日 => \u65e5
let s;
switch (d) {
case 10:
s = '\u521d\u5341';
break;
case 20:
s = '\u4e8c\u5341';
break;
case 30:
s = '\u4e09\u5341';
break;
default :
s = this.nStr2[Math.floor(d / 10)];
s += this.nStr1[d % 10];
}
return (s);
},
/**
* 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是立春
* @param y year
* @return Cn string
* @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
*/
getAnimal: function (y) {
return this.Animals[(y - 4) % 12]
},
/**
* 传入阳历年月日获得详细的公历农历object信息 <=>JSON
* !important! 公历参数区间1900.1.31~2100.12.31
* @param yPara solar year
* @param mPara solar month
* @param dPara solar day
* @return JSON object
* @eg:console.log(calendar.solar2lunar(1987,11,01));
*/
solar2lunar: function (yPara, mPara, dPara) {
let y = parseInt(yPara);
let m = parseInt(mPara);
let d = parseInt(dPara);
//年份限定、上限
if (y < 1900 || y > 2100) {
return -1;// undefined转换为数字变为NaN
}
//公历传参最下限
if (y === 1900 && m === 1 && d < 31) {
return -1;
}
//未传参 获得当天
let objDate;
if (!y) {
objDate = new Date();
} else {
objDate = new Date(y, parseInt(m) - 1, d);
}
let i, leap = 0, temp = 0;
//修正ymd参数
y = objDate.getFullYear();
m = objDate.getMonth() + 1;
d = objDate.getDate();
let offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000;
for (i = 1900; i < 2101 && offset > 0; i++) {
temp = this.lYearDays(i);
offset -= temp;
}
if (offset < 0) {
offset += temp;
i--;
}
//是否今天
let isTodayObj = new Date(),
isToday = false;
if (isTodayObj.getFullYear() === y && isTodayObj.getMonth() + 1 === m && isTodayObj.getDate() === d) {
isToday = true;
}
//星期几
let nWeek = objDate.getDay(),
cWeek = this.nStr1[nWeek];
//数字表示周几顺应天朝周一开始的惯例
if (nWeek === 0) {
nWeek = 7;
}
//农历年
const year = i;
leap = this.leapMonth(i); //闰哪个月
let isLeap = false;
//效验闰月
for (i = 1; i < 13 && offset > 0; i++) {
//闰月
if (leap > 0 && i === (leap + 1) && isLeap === false) {
--i;
isLeap = true;
temp = this.leapDays(year); //计算农历闰月天数
} else {
temp = this.monthDays(year, i);//计算农历普通月天数
}
//解除闰月
if (isLeap === true && i === (leap + 1)) {
isLeap = false;
}
offset -= temp;
}
// 闰月导致数组下标重叠取反
if (offset === 0 && leap > 0 && i === leap + 1) {
if (isLeap) {
isLeap = false;
} else {
isLeap = true;
--i;
}
}
if (offset < 0) {
offset += temp;
--i;
}
//农历月
const month = i;
//农历日
const day = offset + 1;
//天干地支处理
const sm = m - 1;
const gzY = this.toGanZhiYear(year);
// 当月的两个节气
// bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
const firstNode = this.getTerm(y, (m * 2 - 1));//返回当月「节」为几日开始
const secondNode = this.getTerm(y, (m * 2));//返回当月「节」为几日开始
// 依据12节气修正干支月
let gzM = this.toGanZhi((y - 1900) * 12 + m + 11);
if (d >= firstNode) {
gzM = this.toGanZhi((y - 1900) * 12 + m + 12);
}
//传入的日期的节气与否
let isTerm = false;
let Term = null;
if (firstNode === d) {
isTerm = true;
Term = this.solarTerm[m * 2 - 2];
}
if (secondNode === d) {
isTerm = true;
Term = this.solarTerm[m * 2 - 1];
}
//日柱 当月一日与 1900/1/1 相差天数
const dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10;
const gzD = this.toGanZhi(dayCyclical + d - 1);
//该日期所属的星座
const astro = this.toAstro(m, d);
const solarDate = y + '-' + m + '-' + d;
const lunarDate = year + '-' + month + '-' + day;
const festival = this.festival;
const lFestival = this.lFestival;
const festivalDate = m + '-' + d;
let lunarFestivalDate = month + '-' + day;
// bugfix https://github.com/jjonline/calendar.js/issues/29
// 农历节日修正农历12月小月则29号除夕大月则30号除夕
// 此处取巧修正当前为农历12月29号时增加一次判断并且把lunarFestivalDate设置为12-30以正确取得除夕
// 天朝农历节日遇闰月过前不过后的原则此处取农历12月天数不考虑闰月
// 农历润12月在本工具支持的200年区间内仅1574年出现
if (month === 12 && day === 29 && this.monthDays(year, month) === 29) {
lunarFestivalDate = '12-30';
}
return {
date: solarDate,
lunarDate: lunarDate,
festival: festival[festivalDate] ? festival[festivalDate].title : null,
lunarFestival: lFestival[lunarFestivalDate] ? lFestival[lunarFestivalDate].title : null,
'lYear': year,
'lMonth': month,
'lDay': day,
'Animal': this.getAnimal(year),
'IMonthCn': (isLeap ? "\u95f0" : '') + this.toChinaMonth(month),
'IDayCn': this.toChinaDay(day),
'cYear': y,
'cMonth': m,
'cDay': d,
'gzYear': gzY,
'gzMonth': gzM,
'gzDay': gzD,
'isToday': isToday,
'isLeap': isLeap,
'nWeek': nWeek,
'ncWeek': "\u661f\u671f" + cWeek,
'isTerm': isTerm,
'Term': Term,
'astro': astro
};
},
/**
* 传入农历年月日以及传入的月份是否闰月获得详细的公历农历object信息 <=>JSON
* !important! 参数区间1900.1.31~2100.12.1
* @param y lunar year
* @param m lunar month
* @param d lunar day
* @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
* @return JSON object
* @eg:console.log(calendar.lunar2solar(1987,9,10));
*/
lunar2solar: function (y, m, d, isLeapMonth) {
y = parseInt(y)
m = parseInt(m)
d = parseInt(d)
isLeapMonth = !!isLeapMonth;
const leapOffset = 0;
const leapMonth = this.leapMonth(y);
const leapDay = this.leapDays(y);
if (isLeapMonth && (leapMonth !== m)) {
return -1;
}//传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
if (y === 2100 && m === 12 && d > 1 || y === 1900 && m === 1 && d < 31) {
return -1;
}//超出了最大极限值
const day = this.monthDays(y, m);
let _day = day;
//bugFix 2016-9-25
//if month is leap, _day use leapDays method
if (isLeapMonth) {
_day = this.leapDays(y, m);
}
if (y < 1900 || y > 2100 || d > _day) {
return -1;
}//参数合法性效验
//计算农历的时间差
let offset = 0;
let i;
for (i = 1900; i < y; i++) {
offset += this.lYearDays(i);
}
let leap = 0, isAdd = false;
for (i = 1; i < m; i++) {
leap = this.leapMonth(y);
if (!isAdd) {//处理闰月
if (leap <= i && leap > 0) {
offset += this.leapDays(y);
isAdd = true;
}
}
offset += this.monthDays(y, i);
}
//转换闰月农历 需补充该年闰月的前一个月的时差
if (isLeapMonth) {
offset += day;
}
//1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
const strap = Date.UTC(1900, 1, 30, 0, 0, 0);
const calObj = new Date((offset + d - 31) * 86400000 + strap);
const cY = calObj.getUTCFullYear();
const cM = calObj.getUTCMonth() + 1;
const cD = calObj.getUTCDate();
return this.solar2lunar(cY, cM, cD);
}
};
export default calendar;

@ -266,6 +266,8 @@ export enum DICT_TYPE {
MOLD_GET_STATUS = "mold_get_status", MOLD_GET_STATUS = "mold_get_status",
MES_PRE_PRODUCTION = "mes_pre_production", MES_PRE_PRODUCTION = "mes_pre_production",
MES_ZJ_PRODUCT = "mes_zj_product", MES_ZJ_PRODUCT = "mes_zj_product",
FILE_STATUS = "file_status",
Classification = "classification",
//====iot //====iot
IOT_SIEMENS_TYPE = "iot_siemens_type", IOT_SIEMENS_TYPE = "iot_siemens_type",
IOT_MODBUS_TYPE = "iot_modbus_type", IOT_MODBUS_TYPE = "iot_modbus_type",

@ -2,9 +2,9 @@
<div class="home-page"> <div class="home-page">
<div class="home-welcome"> <div class="home-welcome">
<div class="home-welcome-left"> <div class="home-welcome-left">
<div class="home-welcome-title text-white!">欢迎您使用必硕数字化智能中控平台</div> <div class="home-welcome-title text-white!">{{t("home.welcome")}}</div>
<div class="home-welcome-desc text-white! opacity-80"> <div class="home-welcome-desc text-white! opacity-80">
必硕数字化智能中控平台以生产运营为核心统一整合生产计划数据采集仓储设备能源模具质量配方及报表分析等关键业务模块实现从计划到执行从设备到制品从数据到决策的全流程数字化管理 {{t("home.message")}}
</div> </div>
</div> </div>
<div class="home-welcome-right"> <div class="home-welcome-right">
@ -15,11 +15,11 @@ alt="banner" :src="bannerImg" fit="contain" class="home-welcome-image"
</div> </div>
<el-card shadow="never" class="home-section"> <el-card shadow="never" class="home-section">
<div class="section-header"> <div class="section-header">
<div class="section-title">整体生产概况</div> <div class="section-title">{{t("home.productTitle")}}</div>
<div> <div>
<el-date-picker <el-date-picker
v-model="productionOverviewRange" type="daterange" unlink-panels value-format="YYYY-MM-DD" v-model="productionOverviewRange" type="daterange" unlink-panels value-format="YYYY-MM-DD"
start-placeholder="开始日期" end-placeholder="结束日期" size="small" @change="handleProductionOverviewRangeChange" /> :start-placeholder="t('home.placeholderCreateTimeStart')" :end-placeholder="t('home.placeholderCreateTimeEnd')" size="small" @change="handleProductionOverviewRangeChange" />
</div> </div>
</div> </div>
<el-row class="production-overview-row" :gutter="0"> <el-row class="production-overview-row" :gutter="0">
@ -45,14 +45,14 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
</el-card> </el-card>
<el-card shadow="never" class="home-section"> <el-card shadow="never" class="home-section">
<div class="section-header"> <div class="section-header">
<div class="section-title">实时生产进度</div> <div class="section-title">{{t("home.productionSchedule")}}</div>
</div> </div>
<el-carousel height="190px" arrow="always" indicator-position="none" :interval="15000" class="progress-carousel"> <el-carousel height="190px" arrow="always" indicator-position="none" :interval="15000" class="progress-carousel">
<el-carousel-item v-for="(group, index) in productionProgressGroups" :key="index"> <el-carousel-item v-for="(group, index) in productionProgressGroups" :key="index">
<el-row :gutter="16"> <el-row :gutter="16">
<el-col v-for="item in group" :key="item.id" :xl="8" :lg="8" :md="8" :sm="12" :xs="24"> <el-col v-for="item in group" :key="item.id" :xl="8" :lg="8" :md="8" :sm="12" :xs="24">
<div class="progress-card"> <div class="progress-card">
<div class="progress-card-header">生产计划 {{ item.code }} <div class="progress-card-header">{{t("home.productionPlan")}} {{ item.code }}
<el-tag :type="getPlanStatusTagType(item.status)" effect="light"> <el-tag :type="getPlanStatusTagType(item.status)" effect="light">
{{ getPlanStatusLabel(item.status) }} {{ getPlanStatusLabel(item.status) }}
</el-tag> </el-tag>
@ -60,45 +60,45 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<div class="progress-card-body"> <div class="progress-card-body">
<div class="progress-col"> <div class="progress-col">
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">产品名称</span> <span class="progress-label">{{t("home.productionName")}}</span>
<span class="progress-value">{{ item.productName }}</span> <span class="progress-value">{{ item.productName }}</span>
</div> </div>
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">计划数量</span> <span class="progress-label">{{t("home.planNumber")}}</span>
<span class="progress-value">{{ item.planNumber }}</span> <span class="progress-value">{{ item.planNumber }}</span>
</div> </div>
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">生产线</span> <span class="progress-label">{{t("home.productionLine")}}</span>
<span class="progress-value">{{ item.feedingPipelineName }}</span> <span class="progress-value">{{ item.feedingPipelineName }}</span>
</div> </div>
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">计划开始时间</span> <span class="progress-label">{{t("home.planStartTime")}}</span>
<span class="progress-value">{{ formatDate(item.planStartTime) }}</span> <span class="progress-value">{{ formatDate(item.planStartTime) }}</span>
</div> </div>
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">计划结束时间</span> <span class="progress-label">{{t("home.planEndTime")}}</span>
<span class="progress-value">{{ formatDate(item.planEndTime) }}</span> <span class="progress-value">{{ formatDate(item.planEndTime) }}</span>
</div> </div>
</div> </div>
<div class="progress-col"> <div class="progress-col">
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">完工数量</span> <span class="progress-label">{{t("home.completedQuantity")}}</span>
<span class="progress-value">{{ item.wangongNumber }}</span> <span class="progress-value">{{ item.wangongNumber }}</span>
</div> </div>
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">合格数量</span> <span class="progress-label">{{t("home.qualifiedQuantity")}}</span>
<span class="progress-value">{{ item.passNumber }}</span> <span class="progress-value">{{ item.passNumber }}</span>
</div> </div>
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">不合格数量</span> <span class="progress-label">{{t("home.unqualifiedQuantity")}}</span>
<span class="progress-value">{{ item.noPassNumber }}%</span> <span class="progress-value">{{ item.noPassNumber }}%</span>
</div> </div>
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">合格率</span> <span class="progress-label">{{t("home.yieldRate")}}</span>
<span class="progress-value">{{ item.passRate }}</span> <span class="progress-value">{{ item.passRate }}</span>
</div> </div>
<div class="progress-row"> <div class="progress-row">
<span class="progress-label">实际结束时间</span> <span class="progress-label">{{t("home.actualEndTime")}}</span>
<span class="progress-value">{{ formatDate(item.endTime) }}</span> <span class="progress-value">{{ formatDate(item.endTime) }}</span>
</div> </div>
</div> </div>
@ -111,7 +111,7 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
</el-card> </el-card>
<el-card shadow="never" class="home-section"> <el-card shadow="never" class="home-section">
<div class="section-header"> <div class="section-header">
<div class="section-title">待办任务</div> <div class="section-title">{{t("home.gtasks")}}</div>
</div> </div>
<el-carousel height="160px" arrow="always" indicator-position="none" class="todo-carousel" :interval="15000"> <el-carousel height="160px" arrow="always" indicator-position="none" class="todo-carousel" :interval="15000">
<el-carousel-item v-for="(group, index) in todoTaskGroups" :key="index"> <el-carousel-item v-for="(group, index) in todoTaskGroups" :key="index">
@ -119,10 +119,10 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<el-col v-for="item in group" :key="item.id" :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> <el-col v-for="item in group" :key="item.id" :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
<div class="todo-card"> <div class="todo-card">
<div class="todo-title">{{ item.name }}</div> <div class="todo-title">{{ item.name }}</div>
<div class="todo-sub">任务编号{{ item.code }}</div> <div class="todo-sub">{{t("home.missionNumber")}}{{ item.code }}</div>
<div class="todo-sub">任务类型{{ item.type }}</div> <div class="todo-sub">{{t("home.taskType")}}{{ item.type }}</div>
<div class="todo-sub">目标{{ item.deviceName }}</div> <div class="todo-sub">{{t("home.target")}}{{ item.deviceName }}</div>
<div class="todo-sub">创建时间{{ formatDate(item.createTime) }}</div> <div class="todo-sub">{{t("home.creationTime")}}{{ formatDate(item.createTime) }}</div>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
@ -133,7 +133,7 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" class="device-alarm-col"> <el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" class="device-alarm-col">
<el-card shadow="never" class="device-alarm-card"> <el-card shadow="never" class="device-alarm-card">
<div class="section-header"> <div class="section-header">
<div class="section-title">设备</div> <div class="section-title">{{t("home.equipment")}}</div>
<!-- <div class="section-actions"> <!-- <div class="section-actions">
<el-button type="default" size="small">查看文档</el-button> <el-button type="default" size="small">查看文档</el-button>
<el-button type="primary" size="small">添加设备</el-button> <el-button type="primary" size="small">添加设备</el-button>
@ -152,7 +152,7 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" class="device-alarm-col mt-16px xl:mt-0 lg:mt-0"> <el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" class="device-alarm-col mt-16px xl:mt-0 lg:mt-0">
<el-card shadow="never" class="device-alarm-card"> <el-card shadow="never" class="device-alarm-card">
<div class="section-header"> <div class="section-header">
<div class="section-title">模具</div> <div class="section-title">{{t("home.mould")}}</div>
</div> </div>
<el-row :gutter="12" class="mt-16px"> <el-row :gutter="12" class="mt-16px">
<el-col v-for="item in moldStatusCards" :key="item.key" :span="8"> <el-col v-for="item in moldStatusCards" :key="item.key" :span="8">
@ -167,7 +167,7 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
</el-row> </el-row>
<el-card shadow="never" class="home-section"> <el-card shadow="never" class="home-section">
<div class="section-header"> <div class="section-header">
<div class="section-title">采集设备整体情况</div> <div class="section-title">{{t("home.equipmentTile")}}</div>
<!-- <div> <!-- <div>
<el-date-picker <el-date-picker
v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-MM-DD" v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-MM-DD"
@ -177,43 +177,43 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
<el-row class="device-overview-row" :gutter="0" v-model = "formData"> <el-row class="device-overview-row" :gutter="0" v-model = "formData">
<el-col :span="2"> <el-col :span="2">
<div class="device-overview-item"> <div class="device-overview-item">
<div class="production-overview-label">总设备数</div> <div class="production-overview-label">{{t("home.equipmentCount")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.totalDevices }}</div> <div class="production-overview-value production-overview-value-primary">{{ formData?.totalDevices }}</div>
</div> </div>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
<div class="device-overview-item"> <div class="device-overview-item">
<div class="production-overview-label">运行</div> <div class="production-overview-label">{{t("home.operation")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.runningCount }}</div> <div class="production-overview-value production-overview-value-primary">{{ formData?.runningCount }}</div>
</div> </div>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
<div class="device-overview-item"> <div class="device-overview-item">
<div class="production-overview-label">待机中</div> <div class="production-overview-label">{{t("home.standbyMode")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.standbyCount }}</div> <div class="production-overview-value production-overview-value-primary">{{ formData?.standbyCount }}</div>
</div> </div>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
<div class="device-overview-item"> <div class="device-overview-item">
<div class="production-overview-label">故障中</div> <div class="production-overview-label">{{t("home.malfunction")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.faultCount }}</div> <div class="production-overview-value production-overview-value-primary">{{ formData?.faultCount }}</div>
</div> </div>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
<div class="device-overview-item"> <div class="device-overview-item">
<div class="production-overview-label">报警中</div> <div class="production-overview-label">{{t("home.alerting")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.warningCount }}</div> <div class="production-overview-value production-overview-value-primary">{{ formData?.warningCount }}</div>
</div> </div>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
<div class="device-overview-item"> <div class="device-overview-item">
<div class="production-overview-label">利用率</div> <div class="production-overview-label">{{t("home.useRatio")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.utilizationRate }}</div> <div class="production-overview-value production-overview-value-primary">{{ formData?.utilizationRate }}</div>
</div> </div>
</el-col> </el-col>
<el-col :span="2"> <el-col :span="2">
<div class="device-overview-item"> <div class="device-overview-item">
<div class="production-overview-label">故障率</div> <div class="production-overview-label">{{t("home.failureRate")}}</div>
<div class="production-overview-value production-overview-value-primary">{{ formData?.faultRate }}</div> <div class="production-overview-value production-overview-value-primary">{{ formData?.faultRate }}</div>
</div> </div>
</el-col> </el-col>
@ -224,7 +224,7 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
<el-card shadow="never"> <el-card shadow="never">
<template #header> <template #header>
<div class="h-3 flex justify-between"> <div class="h-3 flex justify-between">
<span>设备维修数量统计</span> <span>{{t("home.equipmentTitle")}}</span>
</div> </div>
</template> </template>
<Echart :options="deviceRepairLineOptions" :height="260" /> <Echart :options="deviceRepairLineOptions" :height="260" />
@ -234,7 +234,7 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
<el-card shadow="never"> <el-card shadow="never">
<template #header> <template #header>
<div class="h-3 flex justify-between"> <div class="h-3 flex justify-between">
<span>设备分类统计</span> <span>{{t("home.equipmentClass")}}</span>
</div> </div>
</template> </template>
<Echart :options="deviceCategoryPieOptionsData" :height="260" /> <Echart :options="deviceCategoryPieOptionsData" :height="260" />
@ -244,7 +244,7 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
<el-card shadow="never"> <el-card shadow="never">
<template #header> <template #header>
<div class="h-3 flex justify-between"> <div class="h-3 flex justify-between">
<span>按模具分类统计取模具数量最多的前10项</span> <span>{{t("home.equipmentMessage")}}</span>
</div> </div>
</template> </template>
<Echart :options="moldTypeBarOptionsData" :height="260" /> <Echart :options="moldTypeBarOptionsData" :height="260" />

@ -0,0 +1,158 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="日期" prop="theDay">
<el-date-picker
v-model="formData.theDay"
type="date"
value-format="x"
placeholder="选择日期"
/>
</el-form-item>
<el-form-item label="日期类型" prop="holidayType">
<el-select v-model="formData.holidayType" placeholder="请选择日期类型">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item label="开始时间" prop="startTime">
<el-date-picker
v-model="formData.startTime"
type="date"
value-format="x"
placeholder="选择开始时间"
/>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker
v-model="formData.endTime"
type="date"
value-format="x"
placeholder="选择结束时间"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="预留字段1" prop="attr1">
<el-input v-model="formData.attr1" placeholder="请输入预留字段1" />
</el-form-item>
<el-form-item label="预留字段2" prop="attr2">
<el-input v-model="formData.attr2" placeholder="请输入预留字段2" />
</el-form-item>
<el-form-item label="预留字段3" prop="attr3">
<el-input v-model="formData.attr3" placeholder="请输入预留字段3" />
</el-form-item>
<el-form-item label="预留字段4" prop="attr4">
<el-input v-model="formData.attr4" placeholder="请输入预留字段4" />
</el-form-item>
<el-form-item label="创建者" prop="createBy">
<el-input v-model="formData.createBy" placeholder="请输入创建者" />
</el-form-item>
<el-form-item label="更新者" prop="updateBy">
<el-input v-model="formData.updateBy" placeholder="请输入更新者" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { CalHolidayApi, CalHolidayVO } from '@/api/mes/calholiday'
/** 节假日设置 表单 */
defineOptions({ name: 'CalHolidayForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
holidayId: undefined,
theDay: undefined,
holidayType: undefined,
startTime: undefined,
endTime: undefined,
remark: undefined,
attr1: undefined,
attr2: undefined,
attr3: undefined,
attr4: undefined,
createBy: undefined,
updateBy: undefined,
})
const formRules = reactive({
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await CalHolidayApi.getCalHoliday(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as CalHolidayVO
if (formType.value === 'create') {
await CalHolidayApi.createCalHoliday(data)
message.success(t('common.createSuccess'))
} else {
await CalHolidayApi.updateCalHoliday(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
holidayId: undefined,
theDay: undefined,
holidayType: undefined,
startTime: undefined,
endTime: undefined,
remark: undefined,
attr1: undefined,
attr2: undefined,
attr3: undefined,
attr4: undefined,
createBy: undefined,
updateBy: undefined,
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,377 @@
<template>
<ContentWrap>
<div >
<el-calendar v-model="currentDate" >
<template v-slot:header="{ date }">
<div class="custom-header-with-buttons">
<!-- 左侧标题和统计信息 -->
<div class="header-left">
<div>{{ date }}</div>
</div>
<!-- 自定义操作按钮 -->
<!-- <div class="custom-actions">
</div>-->
<!-- 右侧原按钮 + 自定义按钮 -->
<div class="header-right">
<!-- 原按钮组 -->
<div class="original-buttons">
<el-button-group>
<el-button
type="primary"
size="small"
@click="handleWorkday(date)"
>{{ t('FactoryModeling.CalHoliday.setWorkingDays') }}
</el-button>
<el-button style="margin-left: 10px"
type="success"
size="small"
@click="handleHoliday(date)"
>{{ t('FactoryModeling.CalHoliday.setHoliday') }}
</el-button>
<el-button style="margin-left: 10px"
size="small"
:icon="ArrowLeft"
@click="handleOriginalPrevMonth"
>
{{ t('FactoryModeling.CalHoliday.lastMonth') }}
</el-button>
<el-button
size="small"
@click="handleOriginalToday"
>
{{ t('FactoryModeling.CalHoliday.today') }}
</el-button>
<el-button
size="small"
:icon="ArrowRight"
@click="handleOriginalNextMonth"
>
{{ t('FactoryModeling.CalHoliday.nextMonth') }}</el-button>
</el-button-group>
</div>
</div>
</div>
</template>
<template v-slot:date-cell="{ data }">
<div>
<el-row>
<el-col :span="16">
<div class="solar">
{{ data.day.split('-')[2] }}
</div>
</el-col>
<el-col :span="8">
<el-tag v-if="holidayList.indexOf(data.day) ==-1" effect="dark">{{ t('FactoryModeling.CalHoliday.work') }}</el-tag>
<el-tag v-else effect="dark" type="success">{{ t('FactoryModeling.CalHoliday.rest') }}</el-tag>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<div class="lunar" :class="{ festival : isFestival(date, data) }">{{ solarDate2lunar(data.day) }}</div>
</el-col>
</el-row>
</div>
</template>
</el-calendar>
</div>
</ContentWrap>
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { CalHolidayApi, CalHolidayVO } from '@/api/mes/calholiday'
import dayjs from "dayjs";
import calendar from '@/utils/calendar';
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
import {ElMessage} from "element-plus";
/** 节假日设置 列表 */
defineOptions({ name: 'CalHoliday' })
const message = useMessage() //
const { t } = useI18n() //
const currentDate = ref(new Date())
const holidayList:any = ref([])
const workdayList:any = ref([])
const loading = ref(true) //
const list = ref<CalHolidayVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 100,
theDay: dayjs(currentDate.value).format('YYYY-MM-DD')
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true;
holidayList.value =[];
workdayList.value =[];
try {
const data = await CalHolidayApi.getCalHolidayPage(queryParams)
list.value = data.list
total.value = data.total
if(data.list !=null){
data.list.forEach(theDay => {
if(theDay.holidayType =='HOLIDAY'){
holidayList.value.push(theDay.theDay);
}else{
workdayList.value.push(theDay.theDay);
}
});
}
} finally {
loading.value = false
}
}
//
const loadMonthData = () => {
const year = dayjs(currentDate.value).year()
const month = dayjs(currentDate.value).month() + 1
}
//
const handleOriginalPrevMonth = () => {
queryParams.theDay = dayjs(currentDate.value).format('YYYY-MM-DD');
currentDate.value = dayjs(currentDate.value)
.subtract(1, 'month')
.toDate()
loadMonthData()
getList()
}
const handleOriginalNextMonth = () => {
queryParams.theDay = dayjs(currentDate.value).format('YYYY-MM-DD');
currentDate.value = dayjs(currentDate.value)
.add(1, 'month')
.toDate()
loadMonthData()
getList()
}
const handleOriginalToday = () => {
currentDate.value = new Date();
queryParams.theDay = dayjs(currentDate.value).format('YYYY-MM-DD');
loadMonthData()
}
function isFestival(slotDate, slotData) {
let solarDayArr = slotData.day.split('-');
let lunarDay = calendar.solar2lunar(solarDayArr[0], solarDayArr[1], solarDayArr[2])
// \\
let festAndTerm = [];
festAndTerm.push(lunarDay.festival == null ? '' : ' ' + lunarDay.festival)
festAndTerm.push(lunarDay.lunarFestival == null ? '' : '' + lunarDay.lunarFestival)
festAndTerm.push(lunarDay.Term == null ? '' : '' + lunarDay.Term)
festAndTerm = festAndTerm.join('')
return festAndTerm != ''
}
function solarDate2lunar(solarDate) {
let solar = solarDate.split('-')
let lunar = calendar.solar2lunar(solar[0], solar[1], solar[2])
let lunarMD = lunar.IMonthCn + lunar.IDayCn;
// \\
let festAndTerm = [];
festAndTerm.push(lunar.festival == null ? '' : ' ' + lunar.festival)
festAndTerm.push(lunar.lunarFestival == null ? '' : '' + lunar.lunarFestival)
festAndTerm.push(lunar.Term == null ? '' : '' + lunar.Term)
festAndTerm = festAndTerm.join('')
return festAndTerm == '' ? lunarMD : festAndTerm
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
const props = defineProps<{
}>()
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
//
const getDayInfo = (data: any) => {
const dateStr = dayjs(data.day).format('YYYY-MM-DD')
}
//
const isToday = (date: Date) => {
return dayjs(date).isSame(dayjs(), 'day')
}
const getDayClass = (data: any) => {
const dayInfo = getDayInfo(data)
const classes = []
if (isToday(data.day)) {
classes.push('today')
}
if (dayInfo) {
} else {
//
const day = new Date(data.day).getDay()
if (day === 0 || day === 6) {
classes.push('weekend')
}
}
return classes.join(' ')
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await CalHolidayApi.deleteCalHoliday(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 设置为工作日*/
const handleWorkday = async (date: any) => {
try {
loading.value = true
let value = currentDate.value;
let dateValue = dayjs(value).format('YYYY-MM-DD');
await CalHolidayApi.deleteCalHolidayByDay(dateValue);
message.success(t('设置成功'))
//
await getList();
} catch {
loading.value = false
}
}
/** 设置为节假日*/
const handleHoliday = async (date: any) => {
try {
loading.value = true
let value = currentDate.value;
let dateValue = dayjs(value).format('YYYY-MM-DD');
let sysDate = new Date();
let dateTime = dayjs(sysDate).format('YYYY-MM-DD HH:mm:ss');
let CalHolidayVO:any={
theDay:dateValue,
holidayType:'HOLIDAY',
startTime:dateTime,
endTime:dateTime
}
await CalHolidayApi.createCalHoliday(CalHolidayVO);
message.success(t('设置成功'))
//
await getList();
} catch {
loading.value = false
}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await CalHolidayApi.exportCalHoliday(queryParams)
download.excel(data, '节假日设置.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
<style scoped>
.app-container {
padding: 20px;
}
.el-calendar-table .current:nth-last-child(-n+2) .solar {
color: red;
}
/**本月农历设置为灰色*/
.el-calendar-table .current .lunar {
color: #606266;
font-size: small;
}
/**本月农历节日设置为红色*/
.el-calendar-table .current .lunar.festival {
color: green;
font-size: small;
}
/**节假日背景设置为绿色 */
.el-calendar-table .holiday {
background-color: #88E325;
}
.workday {
background-color: #f0f9eb;
}
.calendar-original-buttons {
position: relative;
padding: 20px;
}
.custom-header-with-buttons {
display: flex;
justify-content: space-between;
align-items: center;
}
.header-left {
display: flex;
flex-direction: column;
gap: 10px;
}
.header-right {
display: flex;
align-items: center;
gap: 20px;
}
:deep(.original-buttons).el-button-group
{
display: flex;
align-items: center;
}
:deep(.el-calendar__header){
border-bottom: var(--el-calendar-header-border-bottom);
display: block !important;;
justify-content: space-between;
padding: 12px 20px;
}
</style>

@ -0,0 +1,237 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" >
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<!-- <el-form-item label="配置编号" prop="configId">
<el-input v-model="formData.configId" placeholder="请输入配置编号" />
</el-form-item>-->
<el-form-item :label="t('FactoryModeling.EsopFile.tableCodeColumn')" prop="code">
<el-input v-model="formData.code" placeholder="点击新增时自动生成" :readonly="true">
<!-- <template #append>
<el-button @click="refreshCode" title="重新生成">
<Refresh />
</el-button>
</template>-->
</el-input>
<!-- <div class="form-tips">此编号为系统自动生成</div>-->
</el-form-item>
<el-form-item :label="t('FactoryModeling.EsopFile.tableNameColumn')" prop="name">
<el-input v-model="formData.name" :placeholder="t('FactoryModeling.EsopFile.searchFileNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('FactoryModeling.EsopFile.searchClassificationLabel')" prop="classification">
<el-select
v-model="formData.classification"
clearable
:placeholder="t('FactoryModeling.EsopFile.searchClassificationPlaceholder')"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.Classification)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="文件类型" prop="type">
<el-input v-model="formData.type" placeholder="请输入文件类型" />
</el-form-item>-->
<el-form-item :label="t('FactoryModeling.EsopFile.searchStatusLabel')" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.FILE_STATUS)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<el-upload
ref="uploadRef"
v-model:file-list="fileList"
:action="uploadUrl"
:auto-upload="false"
:before-upload="beforeUpload"
:data="data"
:disabled="isEdit"
:limit="1"
:on-change="handleFileChange"
:on-error="submitFormError"
:on-exceed="handleExceed"
:on-success="submitFormSuccess"
:http-request="httpRequest"
accept=".jpg, .png, .gif ,.pdf,.word,.excel,.ppt,.pptx,.mp4,.avi,.mov"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text"> {{t('FactoryModeling.EsopFile.messageThree')}} <em>{{t('FactoryModeling.EsopFile.messageFour')}}</em></div>
<template #tip>
<div class="el-upload__tip" style="color: red">
{{t('FactoryModeling.EsopFile.messageOne')}} .jpg, .png, .gif ,.pdf,.word,.excel,.ppt,.pptx,.mp4,.avi,.mov {{t('FactoryModeling.EsopFile.messageTwo')}}
</div>
</template>
</el-upload>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitFileForm">{{t('FactoryModeling.EsopFile.dialogSubmitButton')}}</el-button>
<el-button @click="dialogVisible = false">{{t('FactoryModeling.EsopFile.dialogCancelButton')}}</el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import {useUpload} from "@/views/mes/esopFile/useUpload";
import {FileApi, FileVO} from "@/api/mes/esopFile";
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import {FeedingRecordPlanApi, FeedingRecordPlanVO} from "@/api/mes/feedingplan";
defineOptions({ name: 'InfraFileForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const formLoading = ref(false) //
const isEdit = ref(false)
const fileList = ref([]) //
const data = ref({ path: '' })
const uploadRef = ref()
const dialogTitle = ref('') //
const { uploadUrl, httpRequest } = useUpload()
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
configId: undefined,
code: undefined,
name: undefined,
path: undefined,
url: undefined,
type: undefined,
classification: undefined,
status: 1,
size: undefined,
})
const formRules = reactive({
path: [{ required: true, message: '文件路径不能为空', trigger: 'blur' }],
url: [{ required: true, message: '文件 URL不能为空', trigger: 'blur' }],
status: [{ required: true, message: '文件状态不能为空', trigger: 'blur' }],
size: [{ required: true, message: '文件大小不能为空', trigger: 'blur' }],
})
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
fileList.value =[]
resetForm()
//
if (id) {
formLoading.value = true
isEdit.value = true
try {
formData.value = await FileApi.getFile(id)
let file = {
name: formData.value.name,
url: formData.value.url,
size: formData.value.size,
}
fileList.value.push(file)
} finally {
formLoading.value = false
}
}else{
formData.value = {}
await getGeneratedCode()
}
}
defineExpose({ open }) // open
/** 处理上传的文件发生变化 */
const handleFileChange = (file) => {
data.value.path = file.name
}
const beforeUpload = (file) => {
const isLt2M = file.size / 1024 / 1024 < 100
if (!isLt2M) {
message.error('上传文件大小不能超过 100MB!')
}
return isLt2M
}
/** 提交表单 */
const submitFileForm = async () => {
data.value.params = formData
if(isEdit.value){
//
formLoading.value = true
try {
const data = formData.value as unknown as FileVO
await FileApi.updateFile(data)
message.success(t('common.updateSuccess'))
dialogVisible.value = false
emit('success')
} finally {
formLoading.value = false
}
}else{
isEdit.value=false
if (fileList.value.length == 0) {
message.error('请上传文件')
return
}
unref(uploadRef)?.submit()
}
}
/** 文件上传成功处理 */
const emit = defineEmits(['success']) // success
const submitFormSuccess = () => {
//
dialogVisible.value = false
formLoading.value = false
unref(uploadRef)?.clearFiles()
//
message.success(t('common.createSuccess'))
emit('success')
}
/** 上传错误提示 */
const submitFormError = (): void => {
message.error('上传失败,请您重新上传!')
formLoading.value = false
}
/** 重置表单 */
const resetForm = () => {
//
formLoading.value = false
uploadRef.value?.clearFiles()
}
/** 文件数超出提示 */
const handleExceed = (): void => {
message.error('最多只能上传一个文件!')
}
//
const getGeneratedCode = async () => {
try {
const res = await FileApi.generateCode() //
if (res !== undefined) {
formData.value.code = res
formData.value.status = 1
}
} catch (error) {
console.error('获取编码失败:', error)
//
formData.value.code = 'ESOP_' + Date.now()
}
}
</script>

@ -0,0 +1,234 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
min-label-width="68px"
>
<el-form-item :label="t('FactoryModeling.EsopFile.searchFileNameLabel')" prop="name">
<el-input
v-model="queryParams.name"
:placeholder="t('FactoryModeling.EsopFile.searchFileNamePlaceholder')"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item :label="t('FactoryModeling.EsopFile.searchClassificationLabel')" prop="classification">
<el-select
v-model="queryParams.classification"
:placeholder="t('FactoryModeling.EsopFile.searchClassificationPlaceholder')"
clearable
@keyup.enter="handleQuery"
class="!w-240px">
<el-option
v-for="dict in getDictOptions('classification')" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item :label="t('FactoryModeling.EsopFile.searchStatusLabel')" prop="status">
<el-select
v-model="queryParams.status"
:placeholder="t('FactoryModeling.EsopFile.searchStatusPlaceholder')"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.FILE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> {{t('FactoryModeling.EsopFile.searchButtonText')}}</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> {{t('FactoryModeling.EsopFile.resetButtonText')}}</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['esop:file:create']"
> <Icon icon="ep:plus" class="mr-5px" />
{{t('FactoryModeling.EsopFile.uploadButtonText')}}
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<!-- <el-table-column label="id" align="center" prop="id" />
<el-table-column label="配置编号" align="center" prop="configId" />-->
<el-table-column :label="t('FactoryModeling.EsopFile.tableCodeColumn')" align="center" prop="code" />
<el-table-column :label="t('FactoryModeling.EsopFile.tableNameColumn')" align="center" prop="name" />
<el-table-column :label="t('FactoryModeling.EsopFile.tableClassificationColumn')" align="center" prop="classification" >
<template #default="scope">
<dict-tag type="classification" :value="scope.row.classification" />
</template>
</el-table-column>
<el-table-column :label="t('FactoryModeling.EsopFile.tableTypeColumn')" align="center" prop="type" />
<el-table-column :label="t('FactoryModeling.EsopFile.tableStatusColumn')" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.FILE_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column :label="t('FactoryModeling.EsopFile.tableCreatorNameColumn')" align="center" prop="creatorName" />
<el-table-column
:label="t('FactoryModeling.EsopFile.tableCreateTimeColumn')"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column :label="t('FactoryModeling.EsopFile.tableOperateColumn')" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['esop:file:update']"
>
{{t('FactoryModeling.EsopFile.tableEditAction') }}
</el-button>
<el-button
link
type="primary"
@click="downloadFile(scope.row.url)"
v-hasPermi="['esop:file:update']"
>
{{t('FactoryModeling.EsopFile.tableDownloadAction') }}
</el-button>
<!-- <el-link v-show="scope.row.path" type="primary" download :href="row.url" :underline="false" target="_blank"
>下载</el-link
>-->
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['esop:file:delete']"
>
{{t('FactoryModeling.EsopFile.tableDeleteAction') }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<FileForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { FileApi, FileVO } from '@/api/mes/esopFile'
import FileForm from './FileForm.vue'
import { getDictOptions } from '@/utils/dict'
/** esop文件表库 列表 */
defineOptions({ name: 'EsopFile' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<FileVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
configId: undefined,
code: undefined,
name: undefined,
path: undefined,
url: undefined,
type: undefined,
class: undefined,
status: undefined,
size: undefined,
createTime: [],
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await FileApi.getFilePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await FileApi.deleteFile(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
const downloadFile = (url) => {
window.open(url, '_blank')
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await FileApi.exportFile(queryParams)
download.excel(data, 'esop文件表库.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -0,0 +1,117 @@
import * as FileApi from '@/api/mes/esopFile'
import CryptoJS from 'crypto-js'
import { UploadRawFile, UploadRequestOptions } from 'element-plus/es/components/upload/src/upload'
import axios from 'axios'
/**
* URL
*/
export const getUploadUrl = (): string => {
return import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/esop/file/create'
}
export const useUpload = () => {
// 后端上传地址
const uploadUrl = getUploadUrl()
// 是否使用前端直连上传
const isClientUpload = UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE
// 重写ElUpload上传方法
const httpRequest = async (options: UploadRequestOptions) => {
// 模式一:前端上传
if (isClientUpload) {
const fileName = await generateFileName(options.file)
const presignedInfo = await FileApi.getFilePresignedUrl(fileName)
return axios
.put(presignedInfo.uploadUrl, options.file, {
headers: {
'Content-Type': options.file.type
}
})
.then(() => {
const fileVo = createFile(presignedInfo, fileName, options.file)
return {
code: 0,
status: 0,
data: {
fileName: fileVo.path,
fileUrl: fileVo.url
},
msg: ''
}
})
} else {
const fileVo = {
file: options.file,
code: options.data.params.code,
name: options.data.params.name,
type: options.data.params.type,
classification: options.data.params.classification,
status: options.data.params.status,
}
// 模式二:后端上传
// 重写 el-upload httpRequest 文件上传成功会走成功的钩子,失败走失败的钩子
return new Promise((resolve, reject) => {
FileApi.updateFile(fileVo)
.then((res) => {
if (res.code === 0) {
resolve(res)
} else {
reject(res)
}
})
.catch((res) => {
reject(res)
})
})
}
}
return {
uploadUrl,
httpRequest
}
}
/**
*
* @param vo
* @param name
* @param file
*/
function createFile(vo: FileApi.FilePresignedUrlRespVO, name: string, file: UploadRawFile) {
const fileVo = {
configId: vo.configId,
url: vo.url,
path: name,
name: file.name,
type: file.type,
size: file.size
}
FileApi.createFile(fileVo)
return fileVo
}
/**
* 使SHA256
* @param file
*/
async function generateFileName(file: UploadRawFile) {
// 读取文件内容
const data = await file.arrayBuffer()
const wordArray = CryptoJS.lib.WordArray.create(data)
// 计算SHA256
const sha256 = CryptoJS.SHA256(wordArray).toString()
// 拼接后缀
const ext = file.name.substring(file.name.lastIndexOf('.'))
return `${sha256}${ext}`
}
/**
*
*/
enum UPLOAD_TYPE {
// 客户端直接上传只支持S3服务
CLIENT = 'client',
// 客户端发送到后端上传
SERVER = 'server'
}

@ -13,6 +13,12 @@
:placeholder="t('SystemManagement.Dict.namePlaceholder')" :placeholder="t('SystemManagement.Dict.namePlaceholder')"
/> />
</el-form-item> </el-form-item>
<el-form-item :label="t('SystemManagement.Dict.enName')" prop="enName">
<el-input
v-model="formData.enName"
:placeholder="t('SystemManagement.Dict.enNamePlaceholder')"
/>
</el-form-item>
<el-form-item :label="t('SystemManagement.Dict.type')" prop="type"> <el-form-item :label="t('SystemManagement.Dict.type')" prop="type">
<el-input <el-input
v-model="formData.type" v-model="formData.type"
@ -64,6 +70,7 @@ const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({ const formData = ref({
id: undefined, id: undefined,
name: '', name: '',
enName: '',
type: '', type: '',
status: CommonStatusEnum.ENABLE, status: CommonStatusEnum.ENABLE,
remark: '' remark: ''
@ -127,6 +134,7 @@ const resetForm = () => {
id: undefined, id: undefined,
type: '', type: '',
name: '', name: '',
enName: '',
status: CommonStatusEnum.ENABLE, status: CommonStatusEnum.ENABLE,
remark: '' remark: ''
} }

@ -94,6 +94,12 @@
prop="name" prop="name"
show-overflow-tooltip show-overflow-tooltip
sortable /> sortable />
<el-table-column
align="center"
:label="t('SystemManagement.Dict.enName')"
prop="enName"
show-overflow-tooltip
sortable />
<el-table-column <el-table-column
align="center" align="center"
:label="t('SystemManagement.Dict.type')" :label="t('SystemManagement.Dict.type')"

@ -75,6 +75,7 @@
row-key="id" row-key="id"
> >
<el-table-column :show-overflow-tooltip="true" :label="t('SystemManagement.Menu.name')" prop="name" width="250" sortable /> <el-table-column :show-overflow-tooltip="true" :label="t('SystemManagement.Menu.name')" prop="name" width="250" sortable />
<el-table-column :show-overflow-tooltip="true" :label="t('SystemManagement.Menu.enName')" prop="enName" width="250" sortable />
<el-table-column align="center" :label="t('SystemManagement.Menu.icon')" prop="icon" width="100"> <el-table-column align="center" :label="t('SystemManagement.Menu.icon')" prop="icon" width="100">
<template #default="scope"> <template #default="scope">
<Icon :icon="scope.row.icon" /> <Icon :icon="scope.row.icon" />

Loading…
Cancel
Save