diff --git a/api/index/index.js b/api/index/index.js index fa65633..42903f0 100644 --- a/api/index/index.js +++ b/api/index/index.js @@ -48,5 +48,27 @@ export const taskDetailsWithSmartSort = (params) => { return post('/app-api/homePage/summary/taskDetailsWithSmartSort', params); }; +/** + * 组织 + * @param {Object} params {mobile, password, code} + * @returns {Promise} + */ +export const getCurrentOrg = (params) => { + return get('/app-api/homePage/summary/currentOrg', params); +}; + +/** + * 组织 + * @param {Object} params {mobile, password, code} + * @returns {Promise} + */ +export const orgTaskIndicator = (params) => { + return get('/app-api/homePage/summary/orgTaskIndicator', params); +}; + + + + + diff --git a/manifest.json b/manifest.json index f7c12fd..f35456e 100644 --- a/manifest.json +++ b/manifest.json @@ -54,7 +54,7 @@ }, /* 小程序特有相关 */ "mp-weixin" : { - "appid" : "wx4ba1e0a1b7075371", + "appid" : "wxcb4cd34066b97d82", "setting" : { "urlCheck" : false }, diff --git a/pages-sub/daily/attendanceRecord.vue b/pages-sub/daily/attendanceRecord.vue new file mode 100644 index 0000000..6d83501 --- /dev/null +++ b/pages-sub/daily/attendanceRecord.vue @@ -0,0 +1,387 @@ + + + + + diff --git a/pages-sub/problem/work-order-manage/add-order.vue b/pages-sub/problem/work-order-manage/add-order.vue index 8aa3c50..a0f4d71 100644 --- a/pages-sub/problem/work-order-manage/add-order.vue +++ b/pages-sub/problem/work-order-manage/add-order.vue @@ -2,22 +2,19 @@ - + - - - - + - - - + + - @@ -46,61 +40,60 @@ - + rows="4" @blur="() => workOrderFormRef.value?.validateField('problemDesc')"> - - + - - - - - - - - - - - + + + + + + + - - - + - + + @@ -111,74 +104,37 @@ import { ref, reactive } from 'vue' import { onReady, onShow, onLoad } from '@dcloudio/uni-app'; import { useUploadImgs } from '@/common/utils/useUploadImgs' -import { getRoadListByLatLng } from '@/api/common' +import { getRoadListByLatLng, getProblemListByType } from '@/api/common' import { universalApproval, workorderCreate } from '@/api/work-order-manage/work-order-manage' import { timeFormat } from '@/uni_modules/uview-plus' import { nextStepMap } from '@/common/utils/common' import { useUserStore } from '@/pinia/user'; import { getDictLabel, getDictValue } from '@/common/utils/dict'; - -// ========== 状态管理 ========== const userStore = useUserStore(); - -// ========== 业务线相关状态(核心改造:已整合到workOrderForm中,删除冗余selectedBusiLine) ========== -// 业务线中文名/编码统一取自数据字典 business_line(系统管理 → 字典管理),不再硬编码 const BUSI_LINE_DICT_TYPE = 'business_line'; -// 中文判定:用于区分「传进来的是中文名」还是「传进来的是编码」 const CJK_RE = /[一-龥]/; - -// 业务线选项列表(仅保留name字段=中文名称,适配单选框配置) const busiLineOptions = ref([]); -// 格式化业务线选项(兼容1个/2个/3个的情况,生成中文名称列表) const formatBusiLineOptions = () => { if (!userStore.userInfo?.user?.busiLine) { busiLineOptions.value = []; return; } - const rawBusiLines = userStore.userInfo.user.busiLine.split(','); // 拆分字符串为数组 ["yl", "sz", "wy"] - console.log(rawBusiLines) - // 核心改造:仅生成name字段(值为中文名称),适配单选框:label="item.name" + const rawBusiLines = userStore.userInfo.user.busiLine.split(','); busiLineOptions.value = rawBusiLines.map(item => ({ - name: getBusiLineCnByEn(item.trim()) // name=中文名称(园林/市政/物业) + name: getBusiLineCnByEn(item.trim()) })); - console.log(busiLineOptions.value) }; - - const keyInspectionOptions = reactive([ - { - name: '否', - disabled: false, - }, - { - name: '是', - disabled: false, - }, - + { name: '否', disabled: false }, + { name: '是', disabled: false }, ]); - -// up-radio-group的v-model绑定的值如果设置为某个radio的name,就会被默认选中 -const radiovalue1 = ref('否'); - const groupChange = (n) => { console.log('groupChange', n); }; - -const radioChange = (n) => { - console.log('radioChange', n); -}; - -// ========== 工具方法 ========== -// 编码 → 中文名称。字典未拉到时(登录时字典请求是容错的)兜底显示原始编码, -// 保证选项不为空、页面仍可用 const getBusiLineCnByEn = (busiLineEn) => { if (!busiLineEn) return ''; return getDictLabel(BUSI_LINE_DICT_TYPE, busiLineEn) || busiLineEn; }; - -// ========== 工具方法:通过中文名称获取对应的英文标识 ========== -// 注:字典未拉到时选项里放的就是原始编码,故对「非中文」入参原样返回; -// 中文名解析不到仍返回空串,沿用调用方原有的异常提示 const getBusiLineEnByCn = (cnName) => { if (!cnName) return ''; const code = getDictValue(BUSI_LINE_DICT_TYPE, cnName); @@ -186,10 +142,75 @@ const getBusiLineEnByCn = (cnName) => { return CJK_RE.test(cnName) ? '' : cnName; }; -// ========== 表单Ref ========== -const workOrderFormRef = ref(null) +// ========== 级联选择器变量(和参考页面对齐) ========== +const showCascader = ref(false); +const cascaderValue = ref([]); +const cascaderOptions = ref([]); -// ========== 公共上传逻辑复用 ========== +// 打开级联弹窗 +const openCascader = () => { + console.log('312321dasd') + const busiLineEn = getBusiLineEnByCn(workOrderForm.busiLineCn) + if (!busiLineEn) { + uni.showToast({ title: '请先选择业务线', icon: 'none' }) + return + } + if (!cascaderOptions.value || cascaderOptions.value.length === 0) { + uni.showToast({ title: '正在加载问题类型,请稍等', icon: 'none' }); + loadProblemCascader(busiLineEn); + return; + } + cascaderValue.value = []; + showCascader.value = true; +}; + +/** + * 级联【确认回调】,选中后点确定才赋值,和参考页面保持一致 + */ +const cascaderConfirm = (selectedArr) => { + console.log('最终选中值数组:', selectedArr); + // 递归拼接多级label,用 / 分隔 + const getLabelByValueList = (list, valList) => { + const labelArr = []; + let currentList = list; + for (const val of valList) { + const target = currentList.find(item => item.value === val); + if (!target) break; + labelArr.push(target.label); + currentList = target.children || []; + } + return labelArr.join('/'); + }; + const fullLabel = getLabelByValueList(cascaderOptions.value, selectedArr); + workOrderForm.orderName = fullLabel; + workOrderForm.orderCode = selectedArr.at(-1); + cascaderValue.value = selectedArr; + workOrderFormRef.value?.validateField('orderName'); +}; + +/** + * 加载级联树形数据 + */ +const loadProblemCascader = async (parentCode) => { + if (!parentCode) { + cascaderOptions.value = [] + return + } + try { + uni.showLoading({ title: '加载类型中...' }) + const res = await getProblemListByType({ parentCode }) + uni.hideLoading() + cascaderOptions.value = res || [] + } catch (err) { + uni.hideLoading() + console.error('获取问题类型失败', err) + uni.showToast({ title: '获取问题类型失败', icon: 'none' }) + cascaderOptions.value = [] + } +} + +// 表单Ref +const workOrderFormRef = ref(null) const problemImgs = useUploadImgs({ maxCount: 3, uploadText: '选择问题照片', @@ -197,53 +218,41 @@ const problemImgs = useUploadImgs({ formRef: workOrderFormRef, fieldName: 'problemImgs' }) - -// 无需再手动初始化普通数组,直接使用 ref 响应式数据 if (!Array.isArray(problemImgs.rawImgList.value)) { problemImgs.rawImgList.value = []; } - -// ========== 页面状态 ========== -// 通用弹窗控制 const showActionSheet = ref(false) -// 当前弹窗配置 const currentActionSheetData = reactive({ type: '', list: [], title: '' }) -// 完成时间选择器控制 const show = ref(false) const expectedFinishDate = ref(Date.now()) - -// ========== 重新提交相关状态(核心:本地存储读取) ========== -const isRenew = ref(false); // 是否为重新提交状态 -const renewOrderData = ref(null); // 重新提交的原有工单数据 - -// ========== 下拉列表数据 ========== +const isRenew = ref(false); +const renewOrderData = ref(null); const roadNameList = ref([]) -const orderNameList = ref([]) const pressingTypeList = ref([]) -// ========== 工单表单数据(核心调整:新增busiLineCn字段,绑定业务线) ========== +// ========== 表单数据 ========== const workOrderForm = reactive({ - busiLineCn: '', // 新增:业务线中文名称(用于form绑定、校验、回显) - roadId: 0, // 原有字段 - roadName: '', // 原有字段 - workLocation: '', // 原有字段 - orderName: '', // 原有字段 - pressingType: '', // 原有字段 - pressingTypeName: '', // 原有字段 - problemDesc: '', // 原有字段 - lat: 0, // 原有字段 - lon: 0, // 原有字段 - expectedFinishDate: '', // 原有字段 + busiLineCn: '', + roadId: 0, + roadName: '', + workLocation: '', + orderName: '', + orderCode: '', + pressingType: '', + pressingTypeName: '', + problemDesc: '', + lat: 0, + lon: 0, + expectedFinishDate: '', keyInspection: '否' }) - -// ========== 表单校验规则(核心调整:新增busiLineCn校验规则) ========== +// 表单校验规则:prop改成 orderName,对齐参考页面 const workOrderFormRules = reactive({ - busiLineCn: [ // 新增:业务线必选校验 + busiLineCn: [ { type: 'string', required: true, message: '请选择业务线', trigger: ['change', 'blur'] } ], workLocation: [ @@ -253,7 +262,7 @@ const workOrderFormRules = reactive({ { type: 'string', required: true, message: '请选择道路名称', trigger: ['change', 'blur'] } ], orderName: [ - { type: 'string', required: true, message: '请选择问题类型', trigger: ['change', 'blur'] } + { type: 'string', required: true, message: '请选择问题类型', trigger: 'change' } ], pressingTypeName: [ { type: 'string', required: true, message: '请选择紧急程度', trigger: ['change'] } @@ -262,38 +271,27 @@ const workOrderFormRules = reactive({ { type: 'string', required: true, message: '请输入情况描述', trigger: ['change', 'blur'] }, { type: 'string', min: 3, max: 200, message: '情况描述需3-200字', trigger: ['change', 'blur'] } ], - problemImgs: [problemImgs.imgValidateRule] // 复用上传校验规则 + problemImgs: [problemImgs.imgValidateRule] }) -// ========== 生命周期 ========== -// 页面加载:读取本地存储的工单数据(适配workOrderForm.busiLineCn) onLoad((options) => { - // 初始化业务线选项 formatBusiLineOptions(); - // 默认选中第一个业务线(赋值给workOrderForm.busiLineCn,核心调整) if (busiLineOptions.value.length > 0) { workOrderForm.busiLineCn = busiLineOptions.value[0].name; + const busiLineEn = getBusiLineEnByCn(workOrderForm.busiLineCn) + loadProblemCascader(busiLineEn) } - - // 判断是否为重新提交状态 console.log(options) if (options.isRenew == 1 && options.tempKey) { isRenew.value = true; const tempKey = options.tempKey; - - // 1. 从本地同步存储中读取完整工单数据 try { const orderData = uni.getStorageSync(tempKey); if (orderData && typeof orderData === 'object') { renewOrderData.value = orderData; - - console.log('123213') - console.log(orderData) - // 2. 回显工单数据到表单 echoOrderData(renewOrderData.value); } else { uni.showToast({ title: '工单数据不存在,无法重新提交', icon: 'none' }); - // 跳转回列表页 setTimeout(() => uni.navigateBack(), 1000); return; } @@ -303,106 +301,114 @@ onLoad((options) => { setTimeout(() => uni.navigateBack(), 1000); return; } finally { - // 3. 关键:用完即删,避免本地冗余存储和数据泄露 uni.removeStorageSync(tempKey); } } }); - onReady(() => { - // 设置表单校验规则 if (workOrderFormRef.value) { workOrderFormRef.value.setRules(workOrderFormRules) } console.log('工单表单规则初始化完成') }) - onShow(() => { - console.log(uni.$dict.getDictLabel('ai_image_status', 20)) - console.log(uni.$dict.getDictSimpleList('work_name')) - - // 初始化问题类型列表 - orderNameList.value = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('work_name')) - console.log('问题类型列表:', orderNameList.value) - - // 初始化紧急程度列表 pressingTypeList.value = uni.$dict.transformLabelValueToNameValue(uni.$dict.getDictSimpleList('workorder_pressing_type')) console.log('紧急程度列表:', pressingTypeList.value) }) -// ========== 核心方法:工单数据回显(适配workOrderForm.busiLineCn) ========== -const echoOrderData = (orderItem) => { - // 1. 回显业务线:将工单的英文busiLine转为中文名称,赋值给workOrderForm.busiLineCn(核心调整) - if (orderItem.busiLine) { - workOrderForm.busiLineCn = getBusiLineCnByEn(orderItem.busiLine); // 英文->中文(如wy->物业) +// 回显工单数据【重点对齐参考页面的递归查找级联路径】 +const echoOrderData = async (orderItem) => { + const busiCode = orderItem.busiLine || ''; + if (busiCode) { + workOrderForm.busiLineCn = getBusiLineCnByEn(busiCode); } - - // 2. 原有基础表单字段回显 workOrderForm.roadId = orderItem.roadId || 0; workOrderForm.roadName = orderItem.roadName || ''; workOrderForm.workLocation = orderItem.lonLatAddress || orderItem.roadName || ''; workOrderForm.orderName = orderItem.orderName || ''; + workOrderForm.orderCode = orderItem.orderCode || ''; workOrderForm.pressingType = orderItem.pressingType || ''; workOrderForm.pressingTypeName = uni.$dict.getDictLabel('workorder_pressing_type', orderItem.pressingType) || ''; workOrderForm.problemDesc = orderItem.remark || ''; workOrderForm.lat = orderItem.lat || 0; workOrderForm.lon = orderItem.lon || 0; workOrderForm.expectedFinishDate = orderItem.expectedFinishDate ? timeFormat(orderItem.expectedFinishDate, 'yyyy-mm-dd hh:MM:ss') : ''; -if (orderItem.keyInspection !== undefined) { - workOrderForm.keyInspection = orderItem.keyInspection === 1 ? '是' : '否' -} - // 3. 上传图片回显(兼容useUploadImgs格式) + if (orderItem.keyInspection !== undefined) { + workOrderForm.keyInspection = orderItem.keyInspection === 1 ? '是' : '否' + } if (orderItem.problemsImgs && Array.isArray(orderItem.problemsImgs) && orderItem.problemsImgs.length > 0) { const imgList = orderItem.problemsImgs.map((imgUrl, index) => ({ url: imgUrl, name: `renew_img_${index}`, - status: 'success' // 标记为已上传状态 + status: 'success' })); problemImgs.imgList.value = imgList; problemImgs.rawImgList.value = imgList; } - // 4. 自动获取道路列表(修改:传递当前选中的业务线英文标识) + // ========= 回显核心:加载级联树,递归找到选中路径,赋值 cascaderValue ========= + if (busiCode) { + await loadProblemCascader(busiCode); + const targetCode = orderItem.orderCode + if (targetCode && cascaderOptions.value.length) { + const findCascaderPath = (list, targetVal, path = []) => { + for (const node of list) { + const newPath = [...path, node.value] + if (node.value === targetVal) { + return newPath + } + if (node.children && node.children.length) { + const res = findCascaderPath(node.children, targetVal, newPath) + if (res) return res + } + } + return null + } + const selectPath = findCascaderPath(cascaderOptions.value, targetCode) + if (selectPath) { + cascaderValue.value = selectPath + } + } + } + if (orderItem.lat && orderItem.lon) { - getRoadListByBusiLine(); // 改用封装后的方法,自动携带选中的业务线 + getRoadListByBusiLine(); } }; -// ========== 业务线相关方法(适配workOrderForm.busiLineCn) ========== /** - * 业务线切换事件:清空道路信息 + 重新请求道路列表 + * 业务线切换:清空道路、问题类型级联数据,重新加载级联树 */ const handleBusiLineChange = () => { - // 1. 清空已渲染的道路名称和表单字段 + // 清空道路 workOrderForm.roadName = ''; workOrderForm.roadId = 0; - // 2. 清空道路名称列表数据 roadNameList.value = []; - // 3. 若已选择工单位置,重新请求对应业务线的道路列表 + // 清空问题类型 + workOrderForm.orderName = '' + workOrderForm.orderCode = '' + cascaderValue.value = [] + cascaderOptions.value = [] + const busiLineEn = getBusiLineEnByCn(workOrderForm.busiLineCn) + loadProblemCascader(busiLineEn) if (workOrderForm.workLocation) { getRoadListByBusiLine(); } }; -/** - * 封装:根据当前选中业务线(中文)获取英文标识,再请求道路列表 - */ const getRoadListByBusiLine = async () => { if (!workOrderForm.lat || !workOrderForm.lon) { return; } - // 核心:从workOrderForm.busiLineCn获取中文名称,转为英文标识(核心调整) const busiLineEn = getBusiLineEnByCn(workOrderForm.busiLineCn); if (!busiLineEn) { uni.showToast({ title: '业务线标识异常', icon: 'none' }); return; } - try { uni.showLoading({ title: '获取道路名称中...' }); const roadRes = await getRoadListByLatLng({ - busiLine: busiLineEn, // 传递英文标识(yl/sz/wy),接口正常使用 - // companyCode: 'sls', // 传递英文标识(yl/sz/wy),接口正常使用 + busiLine: busiLineEn, latitude: workOrderForm.lat, longitude: workOrderForm.lon }); @@ -425,115 +431,72 @@ const getRoadListByBusiLine = async () => { } }; -// ========== 通用弹窗方法 ========== -/** - * 打开通用下拉弹窗 - */ +// 通用action-sheet方法 const handleActionSheetOpen = (type) => { - // 道路名称需先校验工单位置是否选择 if (type === 'roadName' && !workOrderForm.workLocation) { uni.showToast({ title: '请先选择工单位置', icon: 'none' }) return } - - // 配置当前弹窗参数 const configMap = { roadName: { title: '请选择道路名称', list: roadNameList.value }, - orderName: { - title: '请选择问题类型', - list: orderNameList.value - }, pressingType: { title: '请选择紧急程度', list: pressingTypeList.value } } - currentActionSheetData.type = type currentActionSheetData.title = configMap[type].title currentActionSheetData.list = configMap[type].list showActionSheet.value = true } - -/** - * 关闭通用下拉弹窗 - */ const handleActionSheetClose = () => { showActionSheet.value = false - // 重置当前弹窗配置 currentActionSheetData.type = '' currentActionSheetData.list = [] currentActionSheetData.title = '' } - -/** - * 通用下拉弹窗选择事件 - */ const handleActionSheetSelect = (e) => { const { type } = currentActionSheetData - // 根据类型处理不同的选择逻辑 switch (type) { case 'roadName': workOrderForm.roadName = e.name workOrderForm.roadId = e.code workOrderFormRef.value?.validateField('roadName') break - case 'orderName': - workOrderForm.orderName = e.name - workOrderFormRef.value?.validateField('orderName') - break case 'pressingType': - console.log(e) workOrderForm.pressingType = e.value workOrderForm.pressingTypeName = e.name workOrderFormRef.value?.validateField('pressingTypeName') break } - // 关闭弹窗 showActionSheet.value = false } -/** - * 返回上一页 - */ const navigateBack = () => { uni.reLaunch({ - url: '/pages-sub/problem/work-order-manage/index', // 列表页路径 + url: '/pages-sub/problem/work-order-manage/index', fail: () => { - // 兜底:若 reLaunch 失败,返回2层(跳过提交页) uni.navigateBack({ delta: 2 }); } }); } - -// 新增:清除希望完成时间的方法 const clearExpectedFinishDate = () => { workOrderForm.expectedFinishDate = '' - // 清除后触发一次字段校验,确保校验状态更新 - // this.$refs.inspectFormRef.validateField('expectedFinishDate') } - -/** - * 选择工单位置 - */ const chooseWorkLocation = () => { uni.chooseLocation({ success: async (res) => { workOrderForm.roadName = '' workOrderForm.roadId = 0 roadNameList.value = [] - workOrderForm.workLocation = res.name workOrderForm.lat = res.latitude workOrderForm.lon = res.longitude - workOrderFormRef.value?.validateField('workLocation') workOrderFormRef.value?.validateField('roadName') - - // 改用封装后的方法,自动携带选中的业务线英文标识 await getRoadListByBusiLine(); }, fail: (err) => { @@ -542,44 +505,28 @@ const chooseWorkLocation = () => { } }) } - -/** - * 完成时间确认 - */ const expectedFinishDateConfirm = (e) => { console.log('选择的完成时间:', e) workOrderForm.expectedFinishDate = timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss') show.value = false } - -/** - * 隐藏键盘 - */ const hideKeyboard = () => { uni.hideKeyboard() } -/** - * 提交工单(区分新增/重新提交,接口隔离:从workOrderForm.busiLineCn取值) - */ const submitWorkOrder = async () => { try { - // 先执行表单校验(包含业务线校验) await workOrderFormRef.value.validate() - - // 核心:从workOrderForm.busiLineCn获取中文名称,转为英文标识(核心调整) const busiLineEn = getBusiLineEnByCn(workOrderForm.busiLineCn); if (!busiLineEn) { uni.showToast({ title: '业务线选择异常,请重新选择', icon: 'none' }); return; } - console.log('完成时间:' + workOrderForm.expectedFinishDate) const keyInspectionVal = workOrderForm.keyInspection === '是' ? 1 : 0 - // 构建公共提交数据 const commonSubmitData = { roadId: workOrderForm.roadId, roadName: workOrderForm.roadName, - problemsImgs: problemImgs.getSuccessImgUrls(), // 复用上传逻辑的URL获取方法 + problemsImgs: problemImgs.getSuccessImgUrls(), remark: workOrderForm.problemDesc.trim(), latLonType: 2, lat: workOrderForm.lat, @@ -587,62 +534,47 @@ const submitWorkOrder = async () => { lonLatAddress: workOrderForm.workLocation, pressingType: workOrderForm.pressingType, orderName: workOrderForm.orderName, + orderCode: workOrderForm.orderCode, keyInspection: keyInspectionVal, expectedFinishDate: workOrderForm.expectedFinishDate == "" ? "" : new Date(workOrderForm.expectedFinishDate).getTime(), sourceId: 1, - sourceName: workOrderForm.busiLineCn, // 从form字段获取业务线中文名称 - busiLine: busiLineEn // 传递英文标识(yl/sz/wy),接口正常使用 + sourceName: workOrderForm.busiLineCn, + busiLine: busiLineEn } - console.log('工单数据') - console.log('完成时间:' + workOrderForm.expectedFinishDate) console.log(commonSubmitData) - // 显示加载中 uni.showLoading({ title: '提交中...' }) let res - - // 核心:根据状态区分接口调用 if (isRenew.value) { - // 重新提交:调用 universalApproval 接口 const renewSubmitData = { - // 原有工单必要参数 workerDataId: renewOrderData.value.id, taskKey: renewOrderData.value.taskKey, taskId: renewOrderData.value.taskId, operateType: nextStepMap[renewOrderData.value.taskKey]?.operateTypeRenew || '', agree: 0, reason: workOrderForm.problemDesc.trim(), - // 新编辑的工单数据 ...commonSubmitData } res = await universalApproval(renewSubmitData) } else { - // 新增工单:调用原有 workorderCreate 接口(不影响原有功能) res = await workorderCreate(commonSubmitData) } - uni.hideLoading() uni.showToast({ title: isRenew.value ? '重新提交成功' : '工单提交成功', icon: 'success', duration: 1000 }) - - // 延迟跳转回列表页 setTimeout(() => { uni.reLaunch({ url: '/pages-sub/problem/work-order-manage/index' }) }, 1000) } catch (error) { - // 隐藏加载框 uni.hideLoading() - - // 区分是表单校验失败还是接口调用失败 if (!Array.isArray(error)) { - // 接口调用失败 console.error(isRenew.value ? '工单重新提交失败:' : '工单提交失败:', error) uni.showToast({ - title: isRenew.value ? error.msg : error.msg, + title: error.msg || '请求异常', icon: 'none', duration: 2000 }) @@ -652,15 +584,11 @@ const submitWorkOrder = async () => { \ No newline at end of file + diff --git a/pages.json b/pages.json index 75dad52..533b064 100644 --- a/pages.json +++ b/pages.json @@ -41,6 +41,13 @@ "navigationBarTitleText": "巡查计划" } }, +{ + "path": "attendanceRecord", + "style": { + "navigationBarTitleText": "考勤记录" + } + }, + { "path": "patrol-manage/pending-plan-detail", "style": { diff --git a/pages/index/index.vue b/pages/index/index.vue index 24cec93..22de183 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -60,12 +60,12 @@ v-for="(baseListItem,baseListIndex) in baseList" :key="baseListIndex" > - - {{baseListItem.num}} + > --> + {{baseListItem.num}} {{baseListItem.title}} @@ -140,113 +140,64 @@ + + diff --git a/uni_modules/uview-plus/components/u-cascader/month.vue b/uni_modules/uview-plus/components/u-cascader/month.vue new file mode 100644 index 0000000..fe85ce1 --- /dev/null +++ b/uni_modules/uview-plus/components/u-cascader/month.vue @@ -0,0 +1,699 @@ + + + + + diff --git a/uni_modules/uview-plus/components/u-cascader/props.js b/uni_modules/uview-plus/components/u-cascader/props.js new file mode 100644 index 0000000..809b33f --- /dev/null +++ b/uni_modules/uview-plus/components/u-cascader/props.js @@ -0,0 +1,246 @@ +import { defineMixin } from '../../libs/vue.js' +import CalendarDefaultProps from './calendar.js' +import { registerComponentProps } from '../../libs/config/props.js' + +const defProps = registerComponentProps(CalendarDefaultProps) +export const props = defineMixin({ + props: { + // 日历顶部标题 + title: { + type: String, + default: () => defProps.calendar.title + }, + // 是否显示标题 + showTitle: { + type: Boolean, + default: () => defProps.calendar.showTitle + }, + // 是否显示副标题 + showSubtitle: { + type: Boolean, + default: () => defProps.calendar.showSubtitle + }, + // 日期类型选择,single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围 + mode: { + type: String, + default: () => defProps.calendar.mode + }, + // mode=range时,第一个日期底部的提示文字 + startText: { + type: String, + default: () => defProps.calendar.startText + }, + // mode=range时,最后一个日期底部的提示文字 + endText: { + type: String, + default: () => defProps.calendar.endText + }, + // 自定义列表 + customList: { + type: Array, + default: () => defProps.calendar.customList + }, + // 主题色,对底部按钮和选中日期有效 + color: { + type: String, + default: () => defProps.calendar.color + }, + // 最小的可选日期 + minDate: { + type: [String, Number], + default: () => defProps.calendar.minDate + }, + // 最大可选日期 + maxDate: { + type: [String, Number], + default: () => defProps.calendar.maxDate + }, + // 默认选中的日期,mode为multiple或range是必须为数组格式 + defaultDate: { + type: [Array, String, Date, null], + default: () => defProps.calendar.defaultDate + }, + // mode=multiple时,最多可选多少个日期 + maxCount: { + type: [String, Number], + default: () => defProps.calendar.maxCount + }, + // 日期行高 + rowHeight: { + type: [String, Number], + default: () => defProps.calendar.rowHeight + }, + // 日期格式化函数 + formatter: { + type: [Function, null], + default: () => defProps.calendar.formatter + }, + // 是否显示农历 + showLunar: { + type: Boolean, + default: () => defProps.calendar.showLunar + }, + // 是否显示月份背景色 + showMark: { + type: Boolean, + default: () => defProps.calendar.showMark + }, + // 确定按钮的文字 + confirmText: { + type: String, + default: () => defProps.calendar.confirmText + }, + // 确认按钮处于禁用状态时的文字 + confirmDisabledText: { + type: String, + default: () => defProps.calendar.confirmDisabledText + }, + // 是否显示日历弹窗 + show: { + type: Boolean, + default: () => defProps.calendar.show + }, + // 是否显示遮罩 + overlay: { + type: Boolean, + default: () => defProps.calendar.overlay + }, + // 动画时长,单位ms + duration: { + type: [String, Number], + default: () => defProps.calendar.duration + }, + // 自定义遮罩的样式 + overlayStyle: { + type: [Object, String], + default: () => defProps.calendar.overlayStyle + }, + // 遮罩的透明度,0-1之间 + overlayOpacity: { + type: [Number, String], + default: () => defProps.calendar.overlayOpacity + }, + // 层级 + zIndex: { + type: [String, Number], + default: () => defProps.calendar.zIndex + }, + // 是否为iPhoneX留出底部安全距离 + safeAreaInsetBottom: { + type: Boolean, + default: () => defProps.calendar.safeAreaInsetBottom + }, + // 是否留出顶部安全距离(状态栏高度) + safeAreaInsetTop: { + type: Boolean, + default: () => defProps.calendar.safeAreaInsetTop + }, + // 弹窗背景色,设置为transparent可去除白色背景 + bgColor: { + type: String, + default: () => defProps.calendar.bgColor + }, + // 是否允许点击遮罩关闭日历 + closeOnClickOverlay: { + type: Boolean, + default: () => defProps.calendar.closeOnClickOverlay + }, + // 是否为只读状态,只读状态下禁止选择日期 + readonly: { + type: Boolean, + default: () => defProps.calendar.readonly + }, + // 是否展示确认按钮 + showConfirm: { + type: Boolean, + default: () => defProps.calendar.showConfirm + }, + // 日期区间最多可选天数,默认无限制,mode = range时有效 + maxRange: { + type: [Number, String], + default: () => defProps.calendar.maxRange + }, + // 范围选择超过最多可选天数时的提示文案,mode = range时有效 + rangePrompt: { + type: String, + default: () => defProps.calendar.rangePrompt + }, + // 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效 + showRangePrompt: { + type: Boolean, + default: () => defProps.calendar.showRangePrompt + }, + // 是否允许日期范围的起止时间为同一天,mode = range时有效 + allowSameDay: { + type: Boolean, + default: () => defProps.calendar.allowSameDay + }, + // 区间模式下确认返回值格式,all-返回区间内所有日期,boundary-仅返回起止日期 + rangeResultMode: { + type: String, + default: () => defProps.calendar.rangeResultMode + }, + // 是否开启时分秒选择 + enableTime: { + type: Boolean, + default: () => defProps.calendar.enableTime + }, + // 时间精度:hour-仅时,minute-时分,second-时分秒 + timePrecision: { + type: String, + default: () => defProps.calendar.timePrecision + }, + // 默认时间,格式支持 HH / HH:mm / HH:mm:ss + defaultTime: { + type: String, + default: () => defProps.calendar.defaultTime + }, + // 圆角值 + round: { + type: [Boolean, String, Number], + default: () => defProps.calendar.round + }, + // 最多展示月份数量 + monthNum: { + type: [Number, String], + default: 3 + }, + // 是否启用非滚动的单月切换模式 + monthSwitch: { + type: Boolean, + default: () => defProps.calendar.monthSwitch + }, + // 是否显示今天按钮 + showToday: { + type: Boolean, + default: () => defProps.calendar.showToday + }, + // 今天日期的独立高亮颜色,默认跟随主题色 + todayColor: { + type: String, + default: () => defProps.calendar.todayColor + }, + // 星期文案 + weekText: { + type: Array, + default: defProps.calendar.weekText + }, + forbidDays: { + type: Array, + default: defProps.calendar.forbidDays + }, + forbidDaysToast:{ + type: String, + default: defProps.calendar.forbidDaysToast + }, + monthFormat:{ + type: String, + default: defProps.calendar.monthFormat + }, + // 是否页面内展示 + pageInline:{ + type: Boolean, + default: defProps.calendar.pageInline + } + } +}) diff --git a/uni_modules/uview-plus/components/u-cascader/u-cascader.vue b/uni_modules/uview-plus/components/u-cascader/u-cascader.vue index 154f359..02061a1 100644 --- a/uni_modules/uview-plus/components/u-cascader/u-cascader.vue +++ b/uni_modules/uview-plus/components/u-cascader/u-cascader.vue @@ -1,360 +1,933 @@ - \ No newline at end of file + + &__time-picker__body { + width: 320px; + height: 200px; + } + + &__time-picker__item { + height: 40px; + line-height: 40px; + text-align: center; + font-size: 16px; + color: #303133; + } + + &__confirm { + padding: 7px 18px; + } +} + diff --git a/uni_modules/uview-plus/components/u-cascader/util.js b/uni_modules/uview-plus/components/u-cascader/util.js new file mode 100644 index 0000000..4483937 --- /dev/null +++ b/uni_modules/uview-plus/components/u-cascader/util.js @@ -0,0 +1,86 @@ +import dayjs from '../u-datetime-picker/dayjs.esm.min.js'; +export default { + methods: { + // 设置月份数据 + setMonth() { + // 月初是周几 + const day = dayjs(this.date).date(1).day() + const start = day == 0 ? 6 : day - 1 + + // 本月天数 + const days = dayjs(this.date).endOf('month').format('D') + + // 上个月天数 + const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D') + + // 日期数据 + const arr = [] + // 清空表格 + this.month = [] + + // 添加上月数据 + arr.push( + ...new Array(start).fill(1).map((e, i) => { + const day = prevDays - start + i + 1 + + return { + value: day, + disabled: true, + date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD') + } + }) + ) + + // 添加本月数据 + arr.push( + ...new Array(days - 0).fill(1).map((e, i) => { + const day = i + 1 + + return { + value: day, + date: dayjs(this.date).date(day).format('YYYY-MM-DD') + } + }) + ) + + // 添加下个月 + arr.push( + ...new Array(42 - days - start).fill(1).map((e, i) => { + const day = i + 1 + + return { + value: day, + disabled: true, + date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD') + } + }) + ) + + // 分割数组 + for (let n = 0; n < arr.length; n += 7) { + this.month.push( + arr.slice(n, n + 7).map((e, i) => { + e.index = i + n + + // 自定义信息 + const custom = this.customList.find((c) => c.date == e.date) + + // 农历 + if (this.lunar) { + const { + IDayCn, + IMonthCn + } = this.getLunar(e.date) + e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn + } + + return { + ...e, + ...custom + } + }) + ) + } + } + } +} diff --git a/uni_modules/uview-plus/libs/config/props.js b/uni_modules/uview-plus/libs/config/props.js index d59c1cd..0298027 100644 --- a/uni_modules/uview-plus/libs/config/props.js +++ b/uni_modules/uview-plus/libs/config/props.js @@ -188,3 +188,11 @@ export default { ...Transition, ...Upload } + +export function registerComponentProps(defaultProps = {}) { + Object.keys(defaultProps || {}).forEach((key) => { + const componentProps = ensureComponentProps(key) + mergeDefaults(componentProps, defaultProps[key]) + }) + return props +} \ No newline at end of file