From f397a6cfd118ae36022576374ed4a1fd9e15448d Mon Sep 17 00:00:00 2001 From: zhangwei <1504152376@qq.com> Date: 星期四, 26 六月 2025 17:13:05 +0800 Subject: [PATCH] '登录注册完善' --- src/router/modules/remaining.ts | 22 src/views/item/index.vue | 506 ++++++++++++++++++ types/index.d.ts | 3 src/views/login/index.vue | 2 src/router/modules/item.ts | 12 src/store/modules/user.ts | 4 src/api/item/index.ts | 148 +++++ src/views/home/index.vue | 263 +++++---- src/utils/http/index.ts | 9 src/views/item/component/editDialog.vue | 193 +++++++ src/utils/commonFunction.ts | 138 +++++ src/router/modules/home.ts | 10 src/utils/auth.ts | 20 src/router/index.ts | 16 src/router/utils.ts | 13 src/api/util.ts | 2 src/utils/formatTime.ts | 207 +++++++ 17 files changed, 1,409 insertions(+), 159 deletions(-) diff --git a/src/api/item/index.ts b/src/api/item/index.ts new file mode 100644 index 0000000..c2e812a --- /dev/null +++ b/src/api/item/index.ts @@ -0,0 +1,148 @@ +/** + * 锛堜笉寤鸿鍐欐垚 request.post(xxx)锛屽洜涓鸿繖鏍� post 鏃讹紝鏃犳硶 params 涓� data 鍚屾椂浼犲弬锛� + * + * 娉ㄥ唽api鎺ュ彛闆嗗悎 + * @method login 鐧诲綍 + */ + +import { http } from "@/utils/http"; +import { baseUrlApi } from "../util"; +type Result = { + success: boolean; + data: Array<any>; +}; + +// 鑾峰彇琛屾斂鍖哄煙鍒楄〃 +export const getRegionList = () => { + return http.request<Result>( + "get", + baseUrlApi("/api/tenderOrder/getRegionList") + ); +}; + +// 鑾峰彇寮�鏍囨柟寮忛泦鍚� +export const getKaibiaofangshiList = () => { + return http.request<Result>( + "get", + baseUrlApi("/api/tenderOrder/getKaibiaofangshiList") + ); +}; + +// 鑾峰彇鏄惁鏋氫妇闆嗗悎 +export const getYesNoEnumList = () => { + return http.request<Result>( + "get", + baseUrlApi("/api/tenderOrder/getYesNoEnumList") + ); +}; + +// 鑾峰彇澶嶅悎浣撴姇鏍囬泦鍚� +export const getFuhetitoubiaoList = () => { + return http.request<Result>( + "get", + baseUrlApi("/api/tenderOrder/getFuhetitoubiaoList") + ); +}; + +// 鑾峰彇瀹氭爣瑙勫垯闆嗗悎 +export const getDingbiaoguizeList = () => { + return http.request<Result>( + "get", + baseUrlApi("/api/tenderOrder/getDingbiaoguizeList") + ); +}; + +// 鑾峰彇浠g爜绫诲瀷闆嗗悎 +export const getDaimaleixingList = () => { + return http.request<Result>( + "get", + baseUrlApi("/api/tenderOrder/getDaimaleixingList") + ); +}; + +// 鑾峰彇閲囪喘鏂瑰紡闆嗗悎 +export const getCaigoufangshiList = () => { + return http.request<Result>( + "get", + baseUrlApi("/api/tenderOrder/getCaigoufangshiList") + ); +}; + +// 鑾峰彇琛屼笟鍝佺洰闆嗗悎 +export const getHangyepingmuList = () => { + return http.request<Result>( + "get", + baseUrlApi("/api/tenderOrder/getHangyepingmuList") + ); +}; + +// 鑾峰彇椤圭洰杩涘害闆嗗悎 +export const getOrderStatusList = () => { + return http.request<Result>( + "get", + baseUrlApi("/api/tenderOrder/getOrderStatusList") + ); +}; + +// 鑾峰彇闈炴斂搴滆鍗曞鐞嗚鎯� +export const getTenderOrderDetail = () => { + return http.request<Result>("get", baseUrlApi("/api/tenderOrder/detail")); +}; + +// 涓嬭浇闈炴斂搴滆鍗曞鐞嗘暟鎹鍏ユā鏉� +export const importFZF = () => { + return http.request<Result>("get", baseUrlApi("/api/tenderOrder/import")); +}; + +// 棣栭〉鏌ヨ闈炴斂搴滆鍗曞鐞� +export const shouyeOrder = (data?: object) => { + return http.request("post", baseUrlApi("/api/tenderOrder/shouyeOrder"), { + data + }); +}; + +// 鎷涙爣浠g悊鍒嗛〉鏌ヨ闈炴斂搴滆鍗曞鐞� +export const zhaobiaoPageOrder = (data?: object) => { + return http.request("post", baseUrlApi("/api/tenderOrder/page"), { data }); +}; + +// 閲囪喘浠g悊浜哄鍔犻潪鏀垮簻璁㈠崟澶勭悊 +export const caigourenAdd = (data?: object) => { + return http.request("post", baseUrlApi("/api/tenderOrder/add"), { data }); +}; + +// 閲囪喘浠g悊浜烘洿鏂伴潪鏀垮簻璁㈠崟澶勭悊 +export const caigourenUpdate = (data?: object) => { + return http.request("post", baseUrlApi("/api/tenderOrder/update"), { data }); +}; + +// 閲囪喘浠g悊浜烘洿鏂伴潪鏀垮簻璁㈠崟璐ㄧ枒 +export const caigourenUpdateZhiyi = (data?: object) => { + return http.request("post", baseUrlApi("/api/tenderOrder/updateZhiyi"), { + data + }); +}; + +// 閲囪喘浠g悊浜烘洿鏂伴潪鏀垮簻璁㈠崟鎶曡瘔 +export const caigourenUpdateTousu = (data?: object) => { + return http.request("post", baseUrlApi("/api/tenderOrder/updateTousu"), { + data + }); +}; + +// 閲囪喘浠g悊浜哄垹闄ら潪鏀垮簻璁㈠崟澶勭悊 +export const caigourenDelete = (data?: object) => { + return http.request("post", baseUrlApi("/api/tenderOrder/delete"), { data }); +}; + +// 閲囪喘浠g悊浜烘壒閲忓垹闄ら潪鏀垮簻璁㈠崟澶勭悊 +export const caigourenBatchDelete = (data?: object) => { + return http.request("post", baseUrlApi("/api/tenderOrder/batchDelete"), { + data + }); +}; + +// 瀵煎嚭闈炴斂搴滆鍗曞鐞嗚褰� +export const exportFZF = (data?: object) => { + return http.request("post", baseUrlApi("/api/tenderOrder/export"), { data }); +}; diff --git a/src/api/util.ts b/src/api/util.ts index 5763e01..c6316ec 100644 --- a/src/api/util.ts +++ b/src/api/util.ts @@ -1,4 +1,4 @@ export const baseUrlApi = (url: string) => process.env.NODE_ENV === "development" ? `/api${url}` - : `http://192.168.0.36:5005${url}`; + : `http://192.168.0.31:5005${url}`; diff --git a/src/router/index.ts b/src/router/index.ts index 91e06ca..a4d8e99 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -106,8 +106,9 @@ } /** 璺敱鐧藉悕鍗� */ -// const whiteList = ["/login"]; -const whiteList = []; +const whiteList = ["/login"]; +const noLoginList = ["/index", "/register", "/registersucess"]; +// const whiteList = []; const { VITE_HIDE_HOME } = import.meta.env; @@ -141,7 +142,7 @@ } // 寮�鍚殣钘忛椤靛悗鍦ㄦ祻瑙堝櫒鍦板潃鏍忔墜鍔ㄨ緭鍏ラ椤祑elcome璺敱鍒欒烦杞埌404椤甸潰 if (VITE_HIDE_HOME === "true" && to.fullPath === "/welcome") { - next({ path: "/error/404" }); + next({ path: "/index" }); } if (_from?.name) { // name涓鸿秴閾炬帴 @@ -194,10 +195,15 @@ } else { if (to.path !== "/login") { if (whiteList.indexOf(to.path) !== -1) { + console.log(to.path, "====1", noLoginList.indexOf(to.path)); next(); } else { - removeToken(); - next({ path: "/login" }); + // if (noLoginList.indexOf(to.path) == -1) { + next(); + // } else { + // removeToken(); + // next({ path: "/login" }); + // } } } else { next(); diff --git a/src/router/modules/home.ts b/src/router/modules/home.ts index ee5224f..1cc1a4f 100644 --- a/src/router/modules/home.ts +++ b/src/router/modules/home.ts @@ -2,13 +2,13 @@ const Layout = () => import("@/layout/index.vue"); export default { - path: "/welcome", - name: "Welcome", + path: "/", + name: "Home", component: Layout, - // redirect: "/welcome", + redirect: "/welcome", meta: { icon: "ep/home-filled", - title: "涓婚〉", + title: "棣栭〉", rank: 0 }, children: [ @@ -17,7 +17,7 @@ name: "Welcome", component: () => import("@/views/welcome/index.vue"), meta: { - title: "涓婚〉", + title: "棣栭〉", showLink: VITE_HIDE_HOME === "true" ? false : true } } diff --git a/src/router/modules/item.ts b/src/router/modules/item.ts new file mode 100644 index 0000000..768d651 --- /dev/null +++ b/src/router/modules/item.ts @@ -0,0 +1,12 @@ +export default { + path: "/item", + component: () => import("@/views/item/index.vue"), + name: "item", + // redirect: "/error/403", + meta: { + icon: "ri/information-line", + // showLink: false, + title: "椤圭洰绠$悊", + rank: 9 + } +} satisfies RouteConfigsTable; diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 621931b..6421398 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -1,19 +1,19 @@ const Layout = () => import("@/layout/index.vue"); export default [ + // { + // path: "/", + // name: "Main", + // redirect: "/home", + // meta: { + // title: "棣栭〉", + // showLink: false, + // rank: 101 + // } + // }, { - path: "/", + path: "/index", name: "Main", - redirect: "/home", - meta: { - title: "棣栭〉", - showLink: false, - rank: 101 - } - }, - { - path: "/home", - name: "Home", component: () => import("@/views/home/index.vue"), meta: { title: "棣栭〉", diff --git a/src/router/utils.ts b/src/router/utils.ts index bb895a1..28e32b8 100644 --- a/src/router/utils.ts +++ b/src/router/utils.ts @@ -33,7 +33,7 @@ const { name, path, parentId, meta } = routeInfo; return isAllEmpty(parentId) ? isAllEmpty(meta?.rank) || - (meta?.rank === 0 && name !== "Welcome" && path !== "/welcome") + (meta?.rank === 0 && name !== "Home" && path !== "/") ? true : false : false; @@ -171,7 +171,7 @@ if (!router.hasRoute(v?.name)) router.addRoute(v); const flattenRouters: any = router .getRoutes() - .find(n => n.path === "/welcome"); + .find(n => n.path === "/"); // 淇濇寔router.options.routes[0].children涓巔ath涓�"/"鐨刢hildren涓�鑷达紝闃叉鏁版嵁涓嶄竴鑷村鑷村紓甯� flattenRouters.children = router.options.routes[0].children; router.addRoute(flattenRouters); @@ -205,8 +205,8 @@ } else { return new Promise(resolve => { getAsyncRoutes().then(({ data }) => { - // handleAsyncRoutes(cloneDeep(data)); - // storageLocal().setItem(key, data); + handleAsyncRoutes(cloneDeep(data)); + storageLocal().setItem(key, data); resolve(router); }); }); @@ -214,7 +214,7 @@ } else { return new Promise(resolve => { getAsyncRoutes().then(({ data }) => { - // handleAsyncRoutes(cloneDeep(data)); + handleAsyncRoutes(cloneDeep(data)); resolve(router); }); }); @@ -249,7 +249,7 @@ if (routesList?.length === 0) return routesList; const newRoutesList: RouteRecordRaw[] = []; routesList.forEach((v: RouteRecordRaw) => { - if (v.path === "/welcome") { + if (v.path === "/") { newRoutesList.push({ component: v.component, name: v.name, @@ -388,6 +388,7 @@ ); tag && useMultiTagsStoreHook().handleTags("push", topMenu); console.log(topMenu, "topMenu"); + return topMenu; } diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 09b6642..cbd4d99 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -68,7 +68,9 @@ return new Promise<UserResult>((resolve, reject) => { getLogin(data) .then(data => { - if (data?.success) setToken(data.data); + console.log(data, "杩欐槸浠�涔堬紵"); + + if (data?.code == 200) setToken(data.result); resolve(data); }) .catch(error => { diff --git a/src/utils/auth.ts b/src/utils/auth.ts index f2b28cb..7e5a326 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -16,7 +16,7 @@ /** 鏄电О */ nickname?: string; /** 褰撳墠鐧诲綍鐢ㄦ埛鐨勮鑹� */ - roles?: Array<string>; + exRoles?: Array<string>; /** 褰撳墠鐧诲綍鐢ㄦ埛鐨勬寜閽骇鍒潈闄� */ permissions?: Array<string>; } @@ -68,11 +68,11 @@ : {} ); - function setUserKey({ avatar, username, nickname, roles, permissions }) { + function setUserKey({ avatar, username, nickname, exRoles, permissions }) { useUserStoreHook().SET_AVATAR(avatar); useUserStoreHook().SET_USERNAME(username); useUserStoreHook().SET_NICKNAME(nickname); - useUserStoreHook().SET_ROLES(roles); + useUserStoreHook().SET_ROLES(exRoles); useUserStoreHook().SET_PERMS(permissions); storageLocal().setItem(userKey, { refreshToken, @@ -80,18 +80,18 @@ avatar, username, nickname, - roles, + exRoles, permissions }); } - if (data.username && data.roles) { - const { username, roles } = data; + if (data.exRoles) { + const { username, exRoles } = data; setUserKey({ avatar: data?.avatar ?? "", username, nickname: data?.nickname ?? "", - roles, + exRoles, permissions: data?.permissions ?? [] }); } else { @@ -101,15 +101,15 @@ storageLocal().getItem<DataInfo<number>>(userKey)?.username ?? ""; const nickname = storageLocal().getItem<DataInfo<number>>(userKey)?.nickname ?? ""; - const roles = - storageLocal().getItem<DataInfo<number>>(userKey)?.roles ?? []; + const exRoles = + storageLocal().getItem<DataInfo<number>>(userKey)?.exRoles ?? []; const permissions = storageLocal().getItem<DataInfo<number>>(userKey)?.permissions ?? []; setUserKey({ avatar, username, nickname, - roles, + exRoles, permissions }); } diff --git a/src/utils/commonFunction.ts b/src/utils/commonFunction.ts new file mode 100644 index 0000000..f911cc8 --- /dev/null +++ b/src/utils/commonFunction.ts @@ -0,0 +1,138 @@ +// 閫氱敤鍑芥暟 +// import useClipboard from "vue-clipboard3"; +// import { ElMessage } from "element-plus"; +import { formatDate } from "@/utils/formatTime"; + +export default function () { + // const { toClipboard } = useClipboard(); + + // 鐧惧垎姣旀牸寮忓寲 + const percentFormat = ( + row: EmptyArrayType, + column: number, + cellValue: string + ) => { + return cellValue ? `${cellValue}%` : "-"; + }; + // 鍒楄〃鏃ユ湡鏃堕棿鏍煎紡鍖� + const dateFormatYMD = ( + row: EmptyArrayType, + column: number, + cellValue: string + ) => { + if (!cellValue) return "-"; + return formatDate(new Date(cellValue), "YYYY-mm-dd"); + }; + // 鍒楄〃鏃ユ湡鏃堕棿鏍煎紡鍖� + const dateFormatYMDHMS = ( + row: EmptyArrayType, + column: number, + cellValue: string + ) => { + if (!cellValue) return "-"; + return formatDate(new Date(cellValue), "YYYY-mm-dd HH:MM:SS"); + }; + // 鍒楄〃鏃ユ湡鏃堕棿鏍煎紡鍖� + const dateFormatHMS = ( + row: EmptyArrayType, + column: number, + cellValue: string + ) => { + if (!cellValue) return "-"; + let time = 0; + if (typeof row === "number") time = row; + if (typeof cellValue === "number") time = cellValue; + return formatDate(new Date(time * 1000), "HH:MM:SS"); + }; + // 灏忔暟鏍煎紡鍖� + const scaleFormat = (value: string = "0", scale: number = 4) => { + return Number.parseFloat(value).toFixed(scale); + }; + // 灏忔暟鏍煎紡鍖� + const scale2Format = (value: string = "0") => { + return Number.parseFloat(value).toFixed(2); + }; + // 鍗冨垎绗︼紝榛樿淇濈暀涓や綅灏忔暟 + const groupSeparator = (value: number, minimumFractionDigits: number = 2) => { + return value.toLocaleString("en-US", { + minimumFractionDigits: minimumFractionDigits, + maximumFractionDigits: 2 + }); + }; + + /** + * 鍒犻櫎瀛楃涓查灏炬寚瀹氬瓧绗� + * @param Str 婧愬瓧绗� + * @param char 鍘婚櫎鐨勬寚瀹氬瓧绗� + * @param type 绫诲瀷锛屽彸杈规垨宸﹁竟锛屼负绌烘槸鏇挎崲棣栧熬 + */ + const trimChar = (Str: string, char: string, type: string) => { + if (char) { + if (type == "left") { + return Str.replace(new RegExp("^\\" + char + "+", "g"), ""); + } else if (type == "right") { + return Str.replace(new RegExp("\\" + char + "+$", "g"), ""); + } + return Str.replace( + new RegExp("^\\" + char + "+|\\" + char + "+$", "g"), + "" + ); + } + return Str.replace(/^\s+|\s+$/g, ""); + }; + // 鐐瑰嚮澶嶅埗鏂囨湰 + // const copyText = (text: string) => { + // return new Promise((resolve, reject) => { + // try { + // //澶嶅埗 + // toClipboard(text); + // //涓嬮潰鍙互璁剧疆澶嶅埗鎴愬姛鐨勬彁绀烘绛夋搷浣� + // ElMessage.success("澶嶅埗鎴愬姛"); + // resolve(text); + // } catch (e) { + // //澶嶅埗澶辫触 + // ElMessage.error("澶嶅埗澶辫触"); + // reject(e); + // } + // }); + // }; + // 鍘绘帀Html鏍囩(鍙栧墠闈�5涓瓧绗�) + const removeHtmlSub = (value: string) => { + const str = value.replace(/<[^>]+>/g, ""); + if (str.length > 50) return str.substring(0, 50) + "......"; + else return str; + }; + // 鍘绘帀Html鏍囩 + const removeHtml = (value: string) => { + return value.replace(/<[^>]+>/g, ""); + }; + // 鑾峰彇鏋氫妇鎻忚堪 + const getEnumDesc = (key: any, lstEnum: any) => { + return lstEnum.find((x: any) => x.value == key)?.describe; + }; + // 杩藉姞query鍙傛暟鍒皍rl + const appendQueryParams = (url: string, params: { [key: string]: any }) => { + if (!params || Object.keys(params).length == 0) return url; + const queryString = Object.keys(params) + .map( + key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}` + ) + .join("&"); + return `${url}${url.includes("?") ? "&" : "?"}${queryString}`; + }; + return { + percentFormat, + dateFormatYMD, + dateFormatYMDHMS, + dateFormatHMS, + scaleFormat, + scale2Format, + groupSeparator, + copyText, + removeHtmlSub, + removeHtml, + getEnumDesc, + appendQueryParams, + trimChar + }; +} diff --git a/src/utils/formatTime.ts b/src/utils/formatTime.ts new file mode 100644 index 0000000..5a95660 --- /dev/null +++ b/src/utils/formatTime.ts @@ -0,0 +1,207 @@ +/** + * 鏃堕棿鏃ユ湡杞崲 + * @param date 褰撳墠鏃堕棿锛宯ew Date() 鏍煎紡 + * @param format 闇�瑕佽浆鎹㈢殑鏃堕棿鏍煎紡瀛楃涓� + * @description format 瀛楃涓查殢鎰忥紝濡� `YYYY-mm銆乊YYY-mm-dd` + * @description format 瀛e害锛�"YYYY-mm-dd HH:MM:SS QQQQ" + * @description format 鏄熸湡锛�"YYYY-mm-dd HH:MM:SS WWW" + * @description format 鍑犲懆锛�"YYYY-mm-dd HH:MM:SS ZZZ" + * @description format 瀛e害 + 鏄熸湡 + 鍑犲懆锛�"YYYY-mm-dd HH:MM:SS WWW QQQQ ZZZ" + * @returns 杩斿洖鎷兼帴鍚庣殑鏃堕棿瀛楃涓� + */ +export function formatDate(date: Date, format: string): string { + const we = date.getDay(); // 鏄熸湡 + const z = getWeek(date); // 鍛� + const qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 瀛e害 + const opt: { [key: string]: string } = { + "Y+": date.getFullYear().toString(), // 骞� + "m+": (date.getMonth() + 1).toString(), // 鏈�(鏈堜唤浠�0寮�濮嬶紝瑕�+1) + "d+": date.getDate().toString(), // 鏃� + "H+": date.getHours().toString(), // 鏃� + "M+": date.getMinutes().toString(), // 鍒� + "S+": date.getSeconds().toString(), // 绉� + "q+": qut // 瀛e害 + }; + // 涓枃鏁板瓧 (鏄熸湡) + const week: { [key: string]: string } = { + "0": "鏃�", + "1": "涓�", + "2": "浜�", + "3": "涓�", + "4": "鍥�", + "5": "浜�", + "6": "鍏�" + }; + // 涓枃鏁板瓧锛堝搴︼級 + const quarter: { [key: string]: string } = { + "1": "涓�", + "2": "浜�", + "3": "涓�", + "4": "鍥�" + }; + if (/(W+)/.test(format)) + format = format.replace( + RegExp.$1, + RegExp.$1.length > 1 + ? RegExp.$1.length > 2 + ? "鏄熸湡" + week[we] + : "鍛�" + week[we] + : week[we] + ); + if (/(Q+)/.test(format)) + format = format.replace( + RegExp.$1, + RegExp.$1.length == 4 ? "绗�" + quarter[qut] + "瀛e害" : quarter[qut] + ); + if (/(Z+)/.test(format)) + format = format.replace( + RegExp.$1, + RegExp.$1.length == 3 ? "绗�" + z + "鍛�" : z + "" + ); + for (const k in opt) { + const r = new RegExp("(" + k + ")").exec(format); + // 鑻ヨ緭鍏ョ殑闀垮害涓嶄负1锛屽垯鍓嶉潰琛ラ浂 + if (r) + format = format.replace( + r[1], + RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, "0") + ); + } + return format; +} + +/** + * 鑾峰彇褰撳墠鏃ユ湡鏄鍑犲懆 + * @param dateTime 褰撳墠浼犲叆鐨勬棩鏈熷�� + * @returns 杩斿洖绗嚑鍛ㄦ暟瀛楀�� + */ +export function getWeek(dateTime: Date): number { + const temptTime = new Date(dateTime.getTime()); + // 鍛ㄥ嚑 + const weekday = temptTime.getDay() || 7; + // 鍛�1+5澶�=鍛ㄥ叚 + temptTime.setDate(temptTime.getDate() - weekday + 1 + 5); + let firstDay = new Date(temptTime.getFullYear(), 0, 1); + const dayOfWeek = firstDay.getDay(); + let spendDay = 1; + if (dayOfWeek != 0) spendDay = 7 - dayOfWeek + 1; + firstDay = new Date(temptTime.getFullYear(), 0, 1 + spendDay); + const d = Math.ceil((temptTime.valueOf() - firstDay.valueOf()) / 86400000); + const result = Math.ceil(d / 7); + return result; +} + +/** + * 灏嗘椂闂磋浆鎹负 `鍑犵鍓峘銆乣鍑犲垎閽熷墠`銆乣鍑犲皬鏃跺墠`銆乣鍑犲ぉ鍓峘 + * @param param 褰撳墠鏃堕棿锛宯ew Date() 鏍煎紡鎴栬�呭瓧绗︿覆鏃堕棿鏍煎紡 + * @param format 闇�瑕佽浆鎹㈢殑鏃堕棿鏍煎紡瀛楃涓� + * @description param 10绉掞細 10 * 1000 + * @description param 1鍒嗭細 60 * 1000 + * @description param 1灏忔椂锛� 60 * 60 * 1000 + * @description param 24灏忔椂锛�60 * 60 * 24 * 1000 + * @description param 3澶╋細 60 * 60* 24 * 1000 * 3 + * @returns 杩斿洖鎷兼帴鍚庣殑鏃堕棿瀛楃涓� + */ +export function formatPast( + param: string | Date, + format: string = "YYYY-mm-dd" +): string { + // 浼犲叆鏍煎紡澶勭悊銆佸瓨鍌ㄨ浆鎹㈠�� + let t: any, s: number; + // 鑾峰彇js 鏃堕棿鎴� + let time: number = new Date().getTime(); + // 鏄惁鏄璞� + typeof param === "string" || "object" + ? (t = new Date(param).getTime()) + : (t = param); + // 褰撳墠鏃堕棿鎴� - 浼犲叆鏃堕棿鎴� + time = Number.parseInt(`${time - t}`); + if (time < 10000) { + // 10绉掑唴 + return "鍒氬垰"; + } else if (time < 60000 && time >= 10000) { + // 瓒呰繃10绉掑皯浜�1鍒嗛挓鍐� + s = Math.floor(time / 1000); + return `${s}绉掑墠`; + } else if (time < 3600000 && time >= 60000) { + // 瓒呰繃1鍒嗛挓灏戜簬1灏忔椂 + s = Math.floor(time / 60000); + return `${s}鍒嗛挓鍓峘; + } else if (time < 86400000 && time >= 3600000) { + // 瓒呰繃1灏忔椂灏戜簬24灏忔椂 + s = Math.floor(time / 3600000); + return `${s}灏忔椂鍓峘; + } else if (time < 259200000 && time >= 86400000) { + // 瓒呰繃1澶╁皯浜�3澶╁唴 + s = Math.floor(time / 86400000); + return `${s}澶╁墠`; + } else { + // 瓒呰繃3澶� + const date = + typeof param === "string" || "object" ? new Date(param) : param; + return formatDate(date, format); + } +} + +/** + * 鏃堕棿闂�欒 + * @param param 褰撳墠鏃堕棿锛宯ew Date() 鏍煎紡 + * @description param 璋冪敤 `formatAxis(new Date())` 杈撳嚭 `涓婂崍濂絗 + * @returns 杩斿洖鎷兼帴鍚庣殑鏃堕棿瀛楃涓� + */ +export function formatAxis(param: Date): string { + const hour: number = new Date(param).getHours(); + if (hour < 6) return "鍑屾櫒濂�"; + else if (hour < 9) return "鏃╀笂濂�"; + else if (hour < 12) return "涓婂崍濂�"; + else if (hour < 14) return "涓崍濂�"; + else if (hour < 17) return "涓嬪崍濂�"; + else if (hour < 19) return "鍌嶆櫄濂�"; + else if (hour < 22) return "鏅氫笂濂�"; + else return "澶滈噷濂�"; +} + +/** + * 鑾峰彇涓や釜鏃堕棿鐩稿樊鐨勭鏁� + * @dateBegin 寮�濮嬫椂闂达紝new Date() 鏍煎紡 + * @dateEnd 缁撴潫鏃堕棿锛宯ew Date() 鏍煎紡 + * @returns 杩斿洖绉掓暟 + */ +export function getTimeDiff(dateBegin: Date, dateEnd: Date) { + const dateDiff = dateEnd.getTime() - dateBegin.getTime(); + return dateDiff / 1000; +} + +/** + * 鏍煎紡鍖栦袱涓椂闂村樊 + * @dateBegin 寮�濮嬫椂闂达紝new Date() 鏍煎紡 + * @dateEnd 缁撴潫鏃堕棿锛宯ew Date() 鏍煎紡 + * @description dateBegin 2025-1-1锛宒ateEnd 2025-1-2 10:10:10 锛� 1澶�10鏃�10鍒�10绉� + * @returns 杩斿洖鎷兼帴鍚庣殑鏃堕棿瀛楃涓� + */ +export function formatTimeDiff(dateBegin: Date, dateEnd: Date) { + const dateDiff = dateEnd.getTime() - dateBegin.getTime(); //鏃堕棿宸殑姣鏁� + const dayDiff = Math.floor(dateDiff / (24 * 3600 * 1000)); //璁$畻鍑虹浉宸ぉ鏁� + const leave1 = dateDiff % (24 * 3600 * 1000); //璁$畻澶╂暟鍚庡墿浣欑殑姣鏁� + const hours = Math.floor(leave1 / (3600 * 1000)); //璁$畻鍑哄皬鏃舵暟 + //璁$畻鐩稿樊鍒嗛挓鏁� + const leave2 = leave1 % (3600 * 1000); //璁$畻灏忔椂鏁板悗鍓╀綑鐨勬绉掓暟 + const minutes = Math.floor(leave2 / (60 * 1000)); //璁$畻鐩稿樊鍒嗛挓鏁� + //璁$畻鐩稿樊绉掓暟 + const leave3 = leave2 % (60 * 1000); //璁$畻鍒嗛挓鏁板悗鍓╀綑鐨勬绉掓暟 + const seconds = Math.round(leave3 / 1000); + let result = ""; + if (dayDiff > 0) { + result += dayDiff + "澶�"; + } + if (hours > 0) { + result += hours + "鏃�"; + } + if (minutes > 0) { + result += minutes + "鍒�"; + } + if (seconds >= 0) { + result += seconds + "绉�"; + } + return result; +} diff --git a/src/utils/http/index.ts b/src/utils/http/index.ts index 19b5be2..298dd29 100644 --- a/src/utils/http/index.ts +++ b/src/utils/http/index.ts @@ -73,7 +73,14 @@ return config; } /** 璇锋眰鐧藉悕鍗曪紝鏀剧疆涓�浜涗笉闇�瑕乣token`鐨勬帴鍙o紙閫氳繃璁剧疆璇锋眰鐧藉悕鍗曪紝闃叉`token`杩囨湡鍚庡啀璇锋眰閫犳垚鐨勬寰幆闂锛� */ - const whiteList = ["/refresh-token", "/login"]; + const whiteList = [ + "/refresh-token", + "/loginPhone", + "/register", + "customerRegistration", + "captcha", + "exRole" + ]; return whiteList.some(url => config.url.endsWith(url)) ? config : new Promise(resolve => { diff --git a/src/views/home/index.vue b/src/views/home/index.vue index 041ec08..9645a61 100644 --- a/src/views/home/index.vue +++ b/src/views/home/index.vue @@ -1,3 +1,4 @@ +el <template> <div class="header"> <img width="227px" height="74px" src="@/assets/home/logo.png" alt="" /> @@ -41,64 +42,71 @@ </div> </div> <div class="right"> - <el-tabs v-model="activeName" class="demo-tabs"> + <!-- <el-tabs v-model="activeName" class="demo-tabs"> <el-tab-pane label="鎰忓悜鍏紑" name="first"> - 鎰忓悜鍏紑 - <!-- <div class="item"> - <span - ><span style="color: #145ccd; font-weight: 600">路</span - >銆愬洓宸濈渷鎴愰兘甯傘��2024骞寸煶鐩樿閬撲粯瀹剁鏉戠伯娌逛骇涓氬洯鍖哄強閰嶅鍩虹璁炬柦寤鸿椤圭洰纾嬪晢鍏憡</span - > - <span>2024-04-15 18:10</span> - </div> - <div class="item"> - <span - ><span style="color: #145ccd; font-weight: 600">路</span - >銆愬洓宸濈渷鎴愰兘甯傘�戠唺鐚胺娓稿涓績灞�閮ㄦ敼閫犻」鐩鍟嗗叕鍛�</span - > - <span>2024-04-15 18:10</span> - </div> - <div class="item"> - <span - ><span style="color: #145ccd; font-weight: 600">路</span - >銆愬洓宸濈渷鎴愰兘甯傘�戜腹鏅閬撴皯婀栫ぞ鍖虹孩鐧藉枩浜嬫湇鍔″満鎵�纾嬪晢鍏憡</span - > - <span>2024-04-15 18:10</span> - </div> - <div class="item"> - <span - ><span style="color: #145ccd; font-weight: 600">路</span - >銆愬洓宸濈渷鎴愰兘甯傘�戞垚閮戒笢閮ㄦ柊鍖轰笁宀旀箹楂樼骇涓浣撹壓涓績鍓嶄复鏃跺仠杞﹀尯鍜屾鏍¢棬涓や晶闂ㄥ崼瀹ら棿鍖哄煙榛戝寲鍙婃帓姘存彁鍗囪В闄ゅ唴娑濋」鐩鍟嗗叕鍛�</span - > - <span>2024-04-15 18:10</span> - </div> - <div class="item"> - <span - ><span style="color: #145ccd; font-weight: 600">路</span - >銆愬洓宸濈渷鎴愰兘甯傘�戝洓宸濈渷鎴愰兘鎴掓瘨搴峰鎵�鐥呮畫鎴掓瘨浜哄憳搴峰娲诲姩涓績缁翠慨鏀归�犻」鐩浜屾纾嬪晢鍏憡</span - > - <span>2024-04-15 18:10</span> - </div> - <div class="item"> - <span - ><span style="color: #145ccd; font-weight: 600">路</span - >銆愬洓宸濈渷鎴愰兘甯傘�戣�佸共閮ㄦ椿鍔ㄤ腑蹇冭淇敼閫犻」鐩鍟嗗叕鍛�</span - > - <span>2024-04-15 18:10</span> - </div> - <div class="item"> - <span - ><span style="color: #145ccd; font-weight: 600">路</span - >銆愬洓宸濈渷鎴愰兘甯傘�戦噾鐗涘尯鎶㈤櫓鏁戠伨宸ョ▼椤圭洰宸ョ▼闃熶紞鍌ㄥ搴擄紙鎴垮缓銆佸競鏀跨被锛夋嫑鏍囧叕鍛�</span - > - <span>2024-04-15 18:10</span> - </div> --> - </el-tab-pane> + 鎰忓悜鍏紑 --> + <div class="item"> + <span + ><span style="color: #145ccd; font-weight: 600">路</span + >銆愬洓宸濈渷鎴愰兘甯傘��2024骞寸煶鐩樿閬撲粯瀹剁鏉戠伯娌逛骇涓氬洯鍖哄強閰嶅鍩虹璁炬柦寤鸿椤圭洰纾嬪晢鍏憡</span + > + <span>2024-04-15 18:10</span> + </div> + <div class="item"> + <span + ><span style="color: #145ccd; font-weight: 600">路</span + >銆愬洓宸濈渷鎴愰兘甯傘�戠唺鐚胺娓稿涓績灞�閮ㄦ敼閫犻」鐩鍟嗗叕鍛�</span + > + <span>2024-04-15 18:10</span> + </div> + <div class="item"> + <span + ><span style="color: #145ccd; font-weight: 600">路</span + >銆愬洓宸濈渷鎴愰兘甯傘�戜腹鏅閬撴皯婀栫ぞ鍖虹孩鐧藉枩浜嬫湇鍔″満鎵�纾嬪晢鍏憡</span + > + <span>2024-04-15 18:10</span> + </div> + <div class="item"> + <span + ><span style="color: #145ccd; font-weight: 600">路</span + >銆愬洓宸濈渷鎴愰兘甯傘�戞垚閮戒笢閮ㄦ柊鍖轰笁宀旀箹楂樼骇涓浣撹壓涓績鍓嶄复鏃跺仠杞﹀尯鍜屾鏍¢棬涓や晶闂ㄥ崼瀹ら棿鍖哄煙榛戝寲鍙婃帓姘存彁鍗囪В闄ゅ唴娑濋」鐩鍟嗗叕鍛�</span + > + <span>2024-04-15 18:10</span> + </div> + <div class="item"> + <span + ><span style="color: #145ccd; font-weight: 600">路</span + >銆愬洓宸濈渷鎴愰兘甯傘�戝洓宸濈渷鎴愰兘鎴掓瘨搴峰鎵�鐥呮畫鎴掓瘨浜哄憳搴峰娲诲姩涓績缁翠慨鏀归�犻」鐩浜屾纾嬪晢鍏憡</span + > + <span>2024-04-15 18:10</span> + </div> + <div class="item"> + <span + ><span style="color: #145ccd; font-weight: 600">路</span + >銆愬洓宸濈渷鎴愰兘甯傘�戣�佸共閮ㄦ椿鍔ㄤ腑蹇冭淇敼閫犻」鐩鍟嗗叕鍛�</span + > + <span>2024-04-15 18:10</span> + </div> + <div class="item"> + <span + ><span style="color: #145ccd; font-weight: 600">路</span + >銆愬洓宸濈渷鎴愰兘甯傘�戦噾鐗涘尯鎶㈤櫓鏁戠伨宸ョ▼椤圭洰宸ョ▼闃熶紞鍌ㄥ搴擄紙鎴垮缓銆佸競鏀跨被锛夋嫑鏍囧叕鍛�</span + > + <span>2024-04-15 18:10</span> + </div> + <div class="item"> + <span + ><span style="color: #145ccd; font-weight: 600">路</span + >銆愬洓宸濈渷鎴愰兘甯傘�戦噾鐗涘尯鎶㈤櫓鏁戠伨宸ョ▼椤圭洰宸ョ▼闃熶紞鍌ㄥ搴擄紙鎴垮缓銆佸競鏀跨被锛夋嫑鏍囧叕鍛�</span + > + <span>2024-04-15 18:10</span> + </div> + <!-- </el-tab-pane> <el-tab-pane label="宸ョ▼鎷涙爣" name="second">宸ョ▼鎷涙爣</el-tab-pane> <el-tab-pane label="璐х墿鎷涙爣" name="third">璐х墿鎷涙爣</el-tab-pane> <el-tab-pane label="鏈嶅姟鎷涙爣" name="fourth">鏈嶅姟鎷涙爣</el-tab-pane> - <el-tab-pane label="缃戜笂绔炰环" name="fourth">缃戜笂绔炰环</el-tab-pane> - </el-tabs> + <el-tab-pane label="缃戜笂绔炰环" name="fourth1">缃戜笂绔炰环</el-tab-pane> + </el-tabs> --> </div> </div> <div class="daixie"> @@ -140,7 +148,7 @@ <div class="user"> <div class="all"> <div class="left"> - <div class="item item1"> + <div v-for="item in state.roleList" :key="item.id" class="item item1"> <div class="box"> <img width="18px" @@ -148,65 +156,44 @@ src="@/assets/home/car1.png" alt="" /> - 閲囪喘浜� + {{ item.name }} </div> <div> - <span class="hover:cursor-pointer" @click="toRegister">娉ㄥ唽</span - ><span class="m-2">|</span - ><span class="hover:cursor-pointer" @click="toLogin">鐧诲綍</span> - </div> - </div> - <div class="item"> - <div class="box"> - <img - width="18px" - height="18px" - src="@/assets/home/car.png" - alt="" - /> - 浠g悊鏈烘瀯 - </div> - <div> - <span class="hover:cursor-pointer" @click="toRegister">娉ㄥ唽</span - ><span class="m-2">|</span - ><span class="hover:cursor-pointer" @click="toLogin">鐧诲綍</span> - </div> - </div> - <div class="item"> - <div class="box"> - <img - width="18px" - height="18px" - src="@/assets/home/car.png" - alt="" - />渚涘簲鍟� - </div> - <div> - <span class="hover:cursor-pointer" @click="toRegister">娉ㄥ唽</span - ><span class="m-2">|</span - ><span class="hover:cursor-pointer" @click="toLogin">鐧诲綍</span> - </div> - </div> - <div class="item"> - <div class="box"> - <img - width="18px" - height="18px" - src="@/assets/home/car.png" - alt="" - />璇勫涓撳 - </div> - <div> - <span class="hover:cursor-pointer" @click="toRegister">娉ㄥ唽</span - ><span class="m-2">|</span - ><span class="hover:cursor-pointer" @click="toLogin">鐧诲綍</span> + <el-link + v-if="state.rolesCode.indexOf(item.code) !== -1" + :underline="false" + class="hover:cursor-pointer" + @click="toRegister" + >閫�鍑�</el-link + > + <el-link + v-else + :underline="false" + class="hover:cursor-pointer" + @click="toRegister" + >鐢宠</el-link + ><span class="m-2">|</span> + <el-link + v-if="state.rolesCode.indexOf(item.code) !== -1" + :underline="false" + class="hover:cursor-pointer" + @click="toWelcome" + >杩涘叆</el-link + > + <el-link + v-else + :underline="false" + class="hover:cursor-pointer" + :disabled="state.accessToken" + @click="toLogin" + >鐧诲綍</el-link + > </div> </div> </div> <div class="right" /> </div> </div> - <div class="more"> <div class="content"> <div class="item"> @@ -399,16 +386,45 @@ </template> <script lang="ts" setup> -import { ref } from "vue"; +import { onMounted, ref, computed, reactive } from "vue"; import myFooter from "./component/myFooter.vue"; -let activeName = ref("first"); +import { useUserStoreHook } from "@/store/modules/user"; +import { exRole } from "@/api/register/index.ts"; +import { storageLocal, isString, isIncludeAllChildren } from "@pureadmin/utils"; + +import { getToken } from "@/utils/auth"; import { useRoute, useRouter } from "vue-router"; defineOptions({ - name: "Home" + name: "Main" }); +let activeName = ref("first"); +/** 瑙掕壊锛堝鏋滄樀绉颁负绌哄垯鏄剧ず鐢ㄦ埛鍚嶏級 */ +const getUseRoles = () => { + state.userInfo = storageLocal().getItem("user-info"); + state.userInfo.exRoles.forEach(element => { + state.rolesCode.push(element.code); + }); +}; +const state = reactive({ + roleList: [], + rolesCode: [], + userInfo: {}, + accessToken: "" +}); +onMounted(() => { + exRole().then(res => { + state.roleList = res.result; + }); + getUseRoles(); + state.accessToken = getToken().accessToken; +}); + const router = useRouter(); const toRegister = () => { router.push({ name: "Register" }); +}; +const toWelcome = () => { + router.push({ name: "Welcome" }); }; const toLogin = () => { router.push({ name: "Login" }); @@ -552,9 +568,12 @@ justify-content: space-between; align-items: center; padding: 0 30px; - height: 25%; + height: 23%; text-align: left; color: #5f5f5f; + // box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; + border-radius: 6px; + margin-bottom: 10px; .box { display: flex; justify-content: center; @@ -569,13 +588,13 @@ color: #ffffff; } } - .left :first-child { - border-top-left-radius: 8px; - border-top-right-radius: 8px; - } - .left *:not(:first-child):not(:last-child) { - border-bottom: #c6c6c6 1px solid; - } + // .left :first-child { + // border-top-left-radius: 8px; + // border-top-right-radius: 8px; + // } + // .left *:not(:first-child):not(:last-child) { + // border-bottom: #c6c6c6 1px solid; + // } .right { background: #a9b3c4; width: 75%; @@ -721,4 +740,14 @@ border-radius: 4px; } } +a { + font-size: 16px; + + // font-weight: 600; + color: #fff; +} +a:hover, +a:active { + color: #fff; +} </style> diff --git a/src/views/item/component/editDialog.vue b/src/views/item/component/editDialog.vue new file mode 100644 index 0000000..b54d199 --- /dev/null +++ b/src/views/item/component/editDialog.vue @@ -0,0 +1,193 @@ +锘�<script lang="ts" name="procurementComplaint" setup> +import { ref, reactive, onMounted } from 'vue'; +import { ElMessage } from 'element-plus'; +import type { FormRules } from 'element-plus'; +import { formatDate } from '/@/utils/formatTime'; +import { useProcurementComplaintApi } from '/@/api/fb_p_complaints/procurementComplaint'; +import { log } from 'console'; + +//鐖剁骇浼犻�掓潵鐨勫嚱鏁帮紝鐢ㄤ簬鍥炶皟 +const emit = defineEmits(['reloadTable']); +const procurementComplaintApi = useProcurementComplaintApi(); +const ruleFormRef = ref(); + +const state = reactive({ + title: '', + loading: false, + showDialog: false, + ruleForm: { + complaints: [{ itemDescription: '' }], + } as any, + stores: {}, + dropdownData: {} as any, +}); + +const handlingStatus = [ + { value: 0, label: '鍏跺畠' }, + { value: 1, label: '鎴愮珛' }, + { value: 2, label: '椹冲洖' }, + { value: 3, label: '閮ㄥ垎鎴愮珛' }, +]; + +// 鑷娣诲姞鍏朵粬瑙勫垯 +const rules = ref<FormRules>({ + projectCode: [{ required: true, message: '璇烽�夋嫨椤圭洰缂栧彿锛�', trigger: 'blur' }], + projectName: [{ required: true, message: '璇烽�夋嫨椤圭洰鍚嶇О锛�', trigger: 'blur' }], + decisionDate: [{ required: true, message: '璇烽�夋嫨鍐冲畾鏃ユ湡锛�', trigger: 'change' }], + purchaser: [{ required: true, message: '璇烽�夋嫨閲囪喘浜猴紒', trigger: 'blur' }], + procurementAgency: [{ required: true, message: '璇烽�夋嫨閲囪喘浠g悊鏈烘瀯锛�', trigger: 'blur' }], +}); + +// 椤甸潰鍔犺浇鏃� +onMounted(async () => {}); + +// 鎵撳紑寮圭獥 +const openDialog = async (row: any, title: string) => { + state.title = title; + row = row ?? { complaints: [{ itemDescription: '' }] }; + state.ruleForm = row.id ? await procurementComplaintApi.detail(row.id).then((res) => res.data.result) : JSON.parse(JSON.stringify(row)); + state.showDialog = true; + console.log(state.ruleForm.complaints, state.ruleForm.complaints.length); +}; + +// 鍏抽棴寮圭獥 +const closeDialog = () => { + emit('reloadTable'); + state.showDialog = false; +}; + +// 鎻愪氦 +const submit = async () => { + ruleFormRef.value.validate(async (isValid: boolean, fields?: any) => { + if (isValid) { + let values = state.ruleForm; + await procurementComplaintApi[state.ruleForm.id ? 'update' : 'add'](values); + closeDialog(); + } else { + ElMessage({ + message: `琛ㄥ崟鏈�${Object.keys(fields).length}澶勯獙璇佸け璐ワ紝璇蜂慨鏀瑰悗鍐嶆彁浜, + type: 'error', + }); + } + }); +}; + +const changeComplaints = (index:any,txt: String) => { + if (txt == 'add') { + state.ruleForm.complaints.splice(index+1, 0, { itemDescription: '' }) + } else { + state.ruleForm.complaints.splice(index, 1) + } +}; + +//灏嗗睘鎬ф垨鑰呭嚱鏁版毚闇茬粰鐖剁粍浠� +defineExpose({ openDialog }); +</script> +<template> + <div class="procurementComplaint-container"> + <el-dialog v-model="state.showDialog" :width="900" draggable :close-on-click-modal="false"> + <template #header> + <div style="color: #fff"> + <span>{{ state.title }}</span> + </div> + </template> + <el-form :model="state.ruleForm" ref="ruleFormRef" label-width="auto" :rules="rules"> + <el-row :gutter="35"> + <el-form-item v-show="false"> + <el-input v-model="state.ruleForm.id" /> + </el-form-item> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="鍐冲畾鏃ユ湡" prop="decisionDate"> + <el-date-picker v-model="state.ruleForm.decisionDate" type="date" placeholder="璇烽�夋嫨鍐冲畾鏃ユ湡" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="椤圭洰鍚嶇О" prop="projectName"> + <el-input v-model="state.ruleForm.projectName" placeholder="璇疯緭鍏ラ」鐩悕绉�" maxlength="200" show-word-limit + clearable /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="椤圭洰缂栧彿" prop="projectCode"> + <el-input v-model="state.ruleForm.projectCode" placeholder="璇疯緭鍏ラ」鐩紪鍙�" maxlength="50" show-word-limit + clearable /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="閲囪喘浜�" prop="purchaser"> + <el-input v-model="state.ruleForm.purchaser" placeholder="璇疯緭鍏ラ噰璐汉" maxlength="100" show-word-limit + clearable /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="閲囪喘浠g悊鏈烘瀯" prop="procurementAgency"> + <el-input v-model="state.ruleForm.procurementAgency" placeholder="璇疯緭鍏ラ噰璐唬鐞嗘満鏋�" maxlength="100" + show-word-limit clearable /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="閲囪喘鐩戠潱閮ㄩ棬" prop="procurementSupervisionDepartment"> + <el-input v-model="state.ruleForm.procurementSupervisionDepartment" placeholder="璇疯緭鍏ラ噰璐洃鐫i儴闂�" + maxlength="100" show-word-limit clearable /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="鎶曡瘔浜�" prop="complainant"> + <el-input v-model="state.ruleForm.complainant" placeholder="璇疯緭鍏ユ姇璇変汉" maxlength="100" show-word-limit + clearable /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="绾夸笂鍦板潃" prop="url"> + <el-input v-model="state.ruleForm.url" placeholder="璇疯緭鍏ョ嚎涓婂湴鍧�" maxlength="255" show-word-limit clearable /> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="20"> + <template v-for="(item,index) in state.ruleForm.complaints" :key="index"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item :label="`鎶曡瘔浜嬮」${index==0?'':index}`" prop="complaints"> + <el-input v-model="item.itemDescription" type="textarea" :placeholder="`璇疯緭鍏ユ姇璇変簨椤�${index==0?'':index}`" + maxlength="1000" show-word-limit clearable /> + </el-form-item> + </el-col> + <el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12" class=""> + <el-form-item :label="`澶勭悊鎻忚堪${index==0?'':index}`" prop="complaints"> + <el-input v-model="item.handlingResult" type="textarea" :placeholder="`璇疯緭鍏ュ鐞嗘弿杩�${index==0?'':index}`" + maxlength="1000" show-word-limit clearable /> + </el-form-item> + </el-col> + <el-col :xs="6" :sm="6" :md="6" :lg="6" :xl="6" class="mb20"> + <el-form-item :label="`鎶曡瘔鐘舵��${index==0?'':index}`" prop="complaints"> + <el-select v-model="item.handlingStatus"> + <el-option v-for="item in handlingStatus" :key="item.value" :label="item.label" :value="item.value" /> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="1" :sm="1" :md="1" :lg="1" :xl="1" class="mb20"> + <el-button type="primary" @click="changeComplaints(index,'add')">+</el-button> + </el-col> + <el-col :xs="1" :sm="1" :md="1" :lg="1" :xl="1" class="mb20" + v-if="state.ruleForm.complaints&&state.ruleForm.complaints.length>1"> + <el-button type="primary" @click="changeComplaints(index)">-</el-button> + </el-col> + <el-divider v-if="state.ruleForm.complaints&&state.ruleForm.complaints.length>1" /> + </template> + + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="() => state.showDialog = false">鍙� 娑�</el-button> + <el-button @click="submit" type="primary" v-reclick="1000">纭� 瀹�</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<style lang="scss" scoped> +:deep(.el-select), +:deep(.el-input-number) { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/item/index.vue b/src/views/item/index.vue new file mode 100644 index 0000000..fa46f25 --- /dev/null +++ b/src/views/item/index.vue @@ -0,0 +1,506 @@ +锘�<script lang="ts" setup name="procurementComplaint"> +import { ref, reactive, onMounted } from "vue"; +import { ElMessageBox, ElMessage } from "element-plus"; +// import { downloadStreamFile } from "@/utils/download"; +import { useProcurementComplaintApi } from "/@/api/fb_p_complaints/procurementComplaint"; +import editDialog from "/@/views/fb_p_complaints/procurementComplaint/component/editDialog.vue"; +import printDialog from "/@/views/system/print/component/hiprint/preview.vue"; +import ModifyRecord from "/@/components/table/modifyRecord.vue"; +import ImportData from "/@/components/table/importData.vue"; +import commonFunction from "@/utils/commonFunction"; + +const { dateFormatYMD } = commonFunction(); +const procurementComplaintApi = useProcurementComplaintApi(); +const printDialogRef = ref(); +const editDialogRef = ref(); +const importDataRef = ref(); +const state = reactive({ + exportLoading: false, + tableLoading: false, + stores: {}, + showAdvanceQueryUI: false, + dropdownData: {} as any, + selectData: [] as any[], + tableQueryParams: {} as any, + tableParams: { + page: 1, + pageSize: 20, + total: 0, + field: "decisionDate", // 榛樿鐨勬帓搴忓瓧娈� + order: "descending", // 鎺掑簭鏂瑰悜 + descStr: "descending" // 闄嶅簭鎺掑簭鐨勫叧閿瓧绗� + }, + tableData: [] +}); + +// 椤甸潰鍔犺浇鏃� +onMounted(async () => {}); + +// 鏌ヨ鎿嶄綔 +const handleQuery = async (params: any = {}) => { + state.tableLoading = true; + state.tableParams = Object.assign(state.tableParams, params); + const result = await procurementComplaintApi + .page(Object.assign(state.tableQueryParams, state.tableParams)) + .then(res => res.data.result); + state.tableParams.total = result?.total; + state.tableData = result?.items ?? []; + state.tableLoading = false; +}; + +// 鍒楁帓搴� +const sortChange = async (column: any) => { + state.tableParams.field = column.prop; + state.tableParams.order = column.order; + await handleQuery(); +}; + +// 鍒犻櫎 +const delProcurementComplaint = (row: any) => { + ElMessageBox.confirm(`纭畾瑕佸垹闄ゅ悧?`, "鎻愮ず", { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + type: "warning" + }) + .then(async () => { + await procurementComplaintApi.delete({ id: row.id }); + handleQuery(); + ElMessage.success("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); +}; + +// 鎵归噺鍒犻櫎 +const batchDelProcurementComplaint = () => { + ElMessageBox.confirm( + `纭畾瑕佸垹闄�${state.selectData.length}鏉¤褰曞悧?`, + "鎻愮ず", + { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + type: "warning" + } + ) + .then(async () => { + await procurementComplaintApi + .batchDelete(state.selectData.map(u => ({ id: u.id }))) + .then(res => { + ElMessage.success(`鎴愬姛鎵归噺鍒犻櫎${res.data.result}鏉¤褰昤); + handleQuery(); + }); + }) + .catch(() => {}); +}; + +// 瀵煎嚭鏁版嵁 +const exportProcurementComplaintCommand = async (command: string) => { + try { + state.exportLoading = true; + if (command === "select") { + const params = Object.assign( + {}, + state.tableQueryParams, + state.tableParams, + { selectKeyList: state.selectData.map(u => u.id) } + ); + await procurementComplaintApi + .exportData(params) + .then(res => downloadStreamFile(res)); + } else if (command === "current") { + const params = Object.assign( + {}, + state.tableQueryParams, + state.tableParams + ); + await procurementComplaintApi + .exportData(params) + .then(res => downloadStreamFile(res)); + } else if (command === "all") { + const params = Object.assign( + {}, + state.tableQueryParams, + state.tableParams, + { page: 1, pageSize: 99999999 } + ); + await procurementComplaintApi + .exportData(params) + .then(res => downloadStreamFile(res)); + } + } finally { + state.exportLoading = false; + } +}; + +handleQuery(); +</script> +<template> + <div v-loading="state.exportLoading" class="procurementComplaint-container"> + <el-card shadow="hover" :body-style="{ paddingBottom: '0' }"> + <el-form ref="queryForm" :model="state.tableQueryParams" labelWidth="90"> + <el-row> + <el-col :xs="24" :sm="12" :md="12" :lg="5" :xl="4" class="mb10"> + <el-form-item label="鍐冲畾鏃ユ湡"> + <el-date-picker + v-model="state.tableQueryParams.decisionDateRange" + type="daterange" + value-format="YYYY-MM-DD HH:mm:ss" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + /> + </el-form-item> + </el-col> + <el-col + v-if="state.showAdvanceQueryUI" + :xs="24" + :sm="12" + :md="12" + :lg="4" + :xl="4" + class="mb10" + > + <el-form-item label="椤圭洰鍚嶇О"> + <el-input + v-model="state.tableQueryParams.projectName" + clearable + placeholder="璇疯緭鍏ラ」鐩悕绉�" + /> + </el-form-item> + </el-col> + <el-col + v-if="state.showAdvanceQueryUI" + :xs="24" + :sm="12" + :md="12" + :lg="4" + :xl="4" + class="mb10" + > + <el-form-item label="椤圭洰缂栧彿"> + <el-input + v-model="state.tableQueryParams.projectCode" + clearable + placeholder="璇疯緭鍏ラ」鐩紪鍙�" + /> + </el-form-item> + </el-col> + <el-col + v-if="state.showAdvanceQueryUI" + :xs="24" + :sm="12" + :md="12" + :lg="4" + :xl="4" + class="mb10" + > + <el-form-item label="閲囪喘浜�"> + <el-input + v-model="state.tableQueryParams.purchaser" + clearable + placeholder="璇疯緭鍏ラ噰璐汉" + /> + </el-form-item> + </el-col> + <el-col + v-if="state.showAdvanceQueryUI" + :xs="24" + :sm="12" + :md="12" + :lg="4" + :xl="4" + class="mb10" + > + <el-form-item label="閲囪喘浠g悊鏈烘瀯"> + <el-input + v-model="state.tableQueryParams.procurementAgency" + clearable + placeholder="璇疯緭鍏ラ噰璐唬鐞嗘満鏋�" + /> + </el-form-item> + </el-col> + <el-col + v-if="state.showAdvanceQueryUI" + :xs="24" + :sm="12" + :md="12" + :lg="5" + :xl="4" + class="mb10" + > + <el-form-item label="閲囪喘鐩戠潱閮ㄩ棬"> + <el-input + v-model=" + state.tableQueryParams.procurementSupervisionDepartment + " + clearable + placeholder="璇疯緭鍏ラ噰璐洃鐫i儴闂�" + /> + </el-form-item> + </el-col> + <el-col + v-if="state.showAdvanceQueryUI" + :xs="24" + :sm="12" + :md="12" + :lg="4" + :xl="4" + class="mb10" + > + <el-form-item label="鎶曡瘔浜�"> + <el-input + v-model="state.tableQueryParams.complainant" + clearable + placeholder="璇疯緭鍏ユ姇璇変汉" + /> + </el-form-item> + </el-col> + <el-col + v-if="state.showAdvanceQueryUI" + :xs="24" + :sm="12" + :md="12" + :lg="4" + :xl="4" + class="mb10" + > + <el-form-item label="鎶曡瘔浜嬮」"> + <el-input + v-model="state.tableQueryParams.keyword" + clearable + placeholder="璇疯緭鍏ユ姇璇変簨椤�" + /> + </el-form-item> + </el-col> + <el-col + v-if="state.showAdvanceQueryUI" + :xs="24" + :sm="12" + :md="12" + :lg="4" + :xl="4" + class="mb10" + > + <el-form-item label="鏄惁鎴愮珛"> + <el-select + v-model="state.tableQueryParams.status" + placeholder="璇烽�夋嫨" + clearable + > + <el-option label="鎴愮珛" value="Valid" /> + <el-option label="椹冲洖" value="Rejected" /> + <el-option label="鍏跺畠" value="Other" /> + </el-select> + </el-form-item> + </el-col> + + <!-- <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10"> + <el-form-item label="鍏抽敭瀛�"> + <el-input v-model="state.tableQueryParams.keyword" clearable placeholder="璇疯緭鍏ユā绯婃煡璇㈠叧閿瓧"/> + </el-form-item> + </el-col> --> + <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10"> + <el-form-item> + <el-button-group style="display: flex; align-items: center"> + <el-button + v-reclick="1000" + type="primary" + icon="ele-Search" + @click="handleQuery" + > + 鏌ヨ + </el-button> + <el-button + icon="ele-Refresh" + @click="() => (state.tableQueryParams = {})" + > + 閲嶇疆 + </el-button> + <el-button + v-if="!state.showAdvanceQueryUI" + icon="ele-ZoomIn" + style="margin-left: 5px" + @click="() => (state.showAdvanceQueryUI = true)" + > + 楂樼骇鏌ヨ + </el-button> + <el-button + v-if="state.showAdvanceQueryUI" + icon="ele-ZoomOut" + style="margin-left: 5px" + @click="() => (state.showAdvanceQueryUI = false)" + > + 闅愯棌 + </el-button> + <el-button + type="danger" + style="margin-left: 5px" + icon="ele-Delete" + :disabled="state.selectData.length == 0" + @click="batchDelProcurementComplaint" + > + 鍒犻櫎 + </el-button> + <el-button + type="primary" + style="margin-left: 5px" + icon="ele-Plus" + @click=" + editDialogRef.openDialog(null, '鏂板鏀垮簻閲囪喘鎶曡瘔鏁版嵁澶勭悊') + " + > + 鏂板 + </el-button> + <!-- <el-dropdown :show-timeout="70" :hide-timeout="50" @command="exportProcurementComplaintCommand"> + <el-button type="primary" style="margin-left:5px;" icon="ele-FolderOpened" v-reclick="20000" + v-auth="'procurementComplaint:export'"> 瀵煎嚭 </el-button> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item command="select" + :disabled="state.selectData.length == 0">瀵煎嚭閫変腑</el-dropdown-item> + <el-dropdown-item command="current">瀵煎嚭鏈〉</el-dropdown-item> + <el-dropdown-item command="all">瀵煎嚭鍏ㄩ儴</el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + <el-button type="warning" style="margin-left:5px;" icon="ele-MostlyCloudy" + @click="importDataRef.openDialog()" v-auth="'procurementComplaint:import'"> 瀵煎叆 </el-button> --> + </el-button-group> + </el-form-item> + </el-col> + </el-row> + </el-form> + </el-card> + <el-card class="full-table" shadow="hover" style="margin-top: 5px"> + <el-table + v-loading="state.tableLoading" + :data="state.tableData" + :default-sort="{ prop: 'decisionDate', order: 'descending' }" + style="width: 100%" + tooltip-effect="light" + row-key="id" + border + @selection-change=" + (val: any[]) => { + state.selectData = val; + } + " + @sort-change="sortChange" + > + <el-table-column type="selection" width="40" align="center" /> + <el-table-column type="index" label="搴忓彿" width="55" align="center" /> + <el-table-column + prop="decisionDate" + label="鍐冲畾鏃ユ湡" + width="90" + show-overflow-tooltip + sortable + > + <template #default="{ row }"> + <span>{{ dateFormatYMD(null, null, row.decisionDate) }}</span> + </template> + </el-table-column> + <el-table-column + prop="projectName" + label="椤圭洰鍚嶇О" + show-overflow-tooltip + /> + <el-table-column + prop="projectCode" + label="椤圭洰缂栧彿" + width="135" + show-overflow-tooltip + /> + <el-table-column + prop="purchaser" + label="閲囪喘浜�" + show-overflow-tooltip + /> + <el-table-column + prop="procurementAgency" + label="閲囪喘浠g悊鏈烘瀯" + show-overflow-tooltip + /> + <el-table-column + prop="complainant" + label="鎶曡瘔浜�" + show-overflow-tooltip + /> + <el-table-column + prop="procurementSupervisionDepartment" + label="閲囪喘鐩戠潱閮ㄩ棬" + width="140" + show-overflow-tooltip + /> + <!-- <el-table-column prop='complaints' label='鏄惁鎴愮珛' show-overflow-tooltip /> --> + <el-table-column prop="url" label="绾夸笂鍦板潃" show-overflow-tooltip> + <template #default="{ row }"> + <el-link underline :href="row.url" target="_blank">{{ + row.url + }}</el-link> + </template> + </el-table-column> + <!-- <el-table-column label="淇敼璁板綍" width="100" align="center" show-overflow-tooltip> + <template #default="scope"> + <ModifyRecord :data="scope.row" /> + </template> + </el-table-column> --> + <el-table-column + label="鎿嶄綔" + width="70" + align="center" + fixed="right" + show-overflow-tooltip + > + <template #default="scope"> + <el-button + icon="ele-Edit" + size="small" + text + type="primary" + @click=" + editDialogRef.openDialog(scope.row, '缂栬緫鏀垮簻閲囪喘鎶曡瘔鏁版嵁澶勭悊') + " + /> + <el-button + icon="ele-Delete" + size="small" + text + type="primary" + @click="delProcurementComplaint(scope.row)" + /> + </template> + </el-table-column> + </el-table> + <el-pagination + v-model:currentPage="state.tableParams.page" + v-model:page-size="state.tableParams.pageSize" + layout="total, sizes, prev, pager, next, jumper" + :page-sizes="[10, 20, 50, 100, 200, 500]" + :total="state.tableParams.total" + size="small" + background + @size-change="(val: any) => handleQuery({ pageSize: val })" + @current-change="(val: any) => handleQuery({ page: val })" + /> + <ImportData + ref="importDataRef" + :import="procurementComplaintApi.importData" + :download="procurementComplaintApi.downloadTemplate" + @refresh="handleQuery" + /> + <printDialog + ref="printDialogRef" + :title="'鎵撳嵃鏀垮簻閲囪喘鎶曡瘔鏁版嵁澶勭悊'" + @reloadTable="handleQuery" + /> + <editDialog ref="editDialogRef" @reloadTable="handleQuery" /> + </el-card> + </div> +</template> +<style scoped> +:deep(.el-input), +:deep(.el-select), +:deep(.el-input-number) { + width: 100%; +} +</style> diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 15a2618..a9ca3a2 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -172,7 +172,7 @@ return initRouter().then(() => { disabled.value = true; router - .push(getTopMenu(true)?.path) + .replace("index") .then(() => { message("鐧诲綍鎴愬姛", { type: "success" }); }) diff --git a/types/index.d.ts b/types/index.d.ts index 404601a..fb58067 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -14,7 +14,8 @@ type ForDataType<T> = { [P in T]?: ForDataType<T[P]>; }; - +// 鐢虫槑 鏁扮粍 +declare type EmptyArrayType<T = any> = T[]; type AnyFunction<T> = (...args: any[]) => T; type PropType<T> = VuePropType<T>; -- Gitblit v1.9.1