diff --git a/dist.rar b/dist.rar index dabd233..df7c820 100644 Binary files a/dist.rar and b/dist.rar differ diff --git a/src/api/system/role.js b/src/api/system/role.js index f13e6f4..e9f35db 100644 --- a/src/api/system/role.js +++ b/src/api/system/role.js @@ -8,6 +8,22 @@ export function listRole(query) { params: query }) } +// 获取角色选择框列表 +export function optionselect(query) { + return request({ + url: '/system/role/optionselect', + method: 'get', + params: query + }) +} + +// 获取菜单角色 +export function getMenu(roleId) { + return request({ + url: '/system/role/getMenu/' + roleId, + method: 'get' + }) +} // 查询角色详细 export function getRole(roleId) { @@ -97,7 +113,15 @@ export function authUserCancelAll(data) { return request({ url: '/system/role/authUser/cancelAll', method: 'put', - params: data + data: data + }) +} +// 批量清除关联账号 +export function authRolecancelAll(data) { + return request({ + url: '/system/role/authRole/cancelAll', + method: 'put', + data: data }) } @@ -106,7 +130,7 @@ export function authUserSelectAll(data) { return request({ url: '/system/role/authUser/selectAll', method: 'put', - params: data + data: data }) } diff --git a/src/api/system/user.js b/src/api/system/user.js index 0085784..6b9fa1a 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -43,13 +43,36 @@ export function delUser(userId) { method: 'delete' }) } +//删除账户/批量删除 +export function deleteUserSystem(data) { + return request({ + url: '/system/user/delete', + method: 'delete', + data: data + }) +} +//冻结账户 +export function changeStatus(data) { + return request({ + url: '/system/user/changeStatus', + method: 'put', + data: data + }) +} +//清空角色 +export function resetRole(data) { + return request({ + url: '/system/user/resetRole', + method: 'put', + data: data + }) +} // 用户密码重置 -export function resetUserPwd(userId, password,codeGoogle) { +export function resetUserPwd(userId,inputGoogleCode) { const data = { userId, - password, - codeGoogle + inputGoogleCode } return request({ url: '/system/user/resetPwd', @@ -58,6 +81,20 @@ export function resetUserPwd(userId, password,codeGoogle) { }) } +// 用户重置谷歌验证码 +export function resetGoogle(userId,inputGoogleCode) { + const data = { + userId, + inputGoogleCode + } + return request({ + url: '/system/user/resetGoogle', + method: 'put', + data: data + }) +} + + // 用户状态修改 export function changeUserStatus(userId, status) { const data = { @@ -89,10 +126,11 @@ export function updateUserProfile(data) { } // 用户密码重置 -export function updateUserPwd(oldPassword, newPassword) { +export function updateUserPwd(oldPassword, newPassword,codeGoogle) { const data = { oldPassword, - newPassword + newPassword, + codeGoogle } return request({ url: '/system/user/profile/updatePwd', @@ -101,6 +139,15 @@ export function updateUserPwd(oldPassword, newPassword) { }) } +// 修改密码 +export function updateUserPassword(data) { + return request({ + url: '/system/user/profile/change/password', + method: 'put', + data: data + }) +} + // 用户头像上传 export function uploadAvatar(data) { return request({ @@ -136,11 +183,10 @@ export function deptTreeSelect() { }) } -// 修改密码 -export function updateUserPassword(data) { +// 用户名称检查 +export function getSystemUserCheck(userName) { return request({ - url: '/resetPwd', - method: 'post', - data: data + url: '/system/user/check/' + userName, + method: 'get' }) } diff --git a/src/components/TableBatchOperate/index.vue b/src/components/TableBatchOperate/index.vue new file mode 100644 index 0000000..26f6095 --- /dev/null +++ b/src/components/TableBatchOperate/index.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue index 1ba2047..a977d74 100644 --- a/src/layout/components/Sidebar/index.vue +++ b/src/layout/components/Sidebar/index.vue @@ -27,17 +27,19 @@ /> --> -
- -
- - +
+ +
+ + {{ nickName }}
+ + + + + + {{ formData.userName }} + + + + + + + + {{ t('已设置') }} + + + 修改密码 + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -60,19 +117,49 @@ import useAppStore from '@/store/modules/app' import useSettingsStore from '@/store/modules/settings' import usePermissionStore from '@/store/modules/permission' import useUserStore from '@/store/modules/user' - +import { getLocalStorage } from "@/utils/auth"; +import { updateUserProfile,getUserProfile,updateUserPwd } from "@/api/system/user"; const route = useRoute(); const appStore = useAppStore() const userStore = useUserStore() const settingsStore = useSettingsStore() const permissionStore = usePermissionStore() - +const { proxy } = getCurrentInstance() const sidebarRouters = computed(() => permissionStore.sidebarRouters); const showLogo = computed(() => settingsStore.sidebarLogo); const sideTheme = computed(() => settingsStore.sideTheme); const theme = computed(() => settingsStore.theme); const windowWidth = ref(window.innerWidth) +const nickName = ref(getLocalStorage('userInfo')?.nickName); + +const dialogVisible = ref(false); +const rules = ref({ +}); +const formData = ref({ +}); +const oldForm = shallowRef({ }); +const passwordDialogVisible = ref(false); +const passwordFormData = ref({ + oldPassword: undefined, + newPassword: undefined, + confirmPassword: undefined, + codeGoogle: undefined +}); + +const equalToPassword = (rule, value, callback) => { + if (passwordFormData.value.newPassword !== value) { + callback(new Error("两次输入的密码不一致")); + } else { + callback(); + } +}; +const rulesPassword = ref({ + oldPassword: [{ required: true, message: "旧密码不能为空", trigger: "change" }], + newPassword: [{ required: true, message: "新密码不能为空", trigger: "change" }, { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "change" }, { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "change" }], + confirmPassword: [{ required: true, message: "确认密码不能为空", trigger: "change" }, { required: true, validator: equalToPassword, trigger: "change" }], + codeGoogle: [{ required: true, message: "谷歌验证码不能为空", trigger: "change" }] +}); function updateWidth() { windowWidth.value = window.innerWidth @@ -125,6 +212,51 @@ function logout() { }) }).catch(() => { }); } +const handleClick = () => { + getUserProfile().then(response => { + formData.value = response.data; + dialogVisible.value = true; + nextTick(() => { + oldForm.value = JSON.stringify(formData.value); + }) + }); +} +const closeDialog = () => { + dialogVisible.value = false; +} +//修改密码 +const updatePassword = () => { + passwordDialogVisible.value = true; +} +const submitForm = () => { + proxy.$refs.userRef.validate(valid => { + if (valid) { + if (JSON.stringify(formData.value) != oldForm.value) { + updateUserProfile(formData.value).then(response => { + proxy.$modal.msgSuccess("修改成功"); + nickName.value = formData.value.nickName; + dialogVisible.value = false; + }); + }else{ + dialogVisible.value = false; + } + } + }); +} + +const closePasswordDialog = () => { + passwordDialogVisible.value = false; +} +const submitPasswordForm = () => { + proxy.$refs.passwordRef.validate(valid => { + if (valid) { + updateUserPwd(passwordFormData.value.oldPassword, passwordFormData.value.newPassword,passwordFormData.value.codeGoogle).then(response => { + proxy.$modal.msgSuccess("修改成功"); + passwordDialogVisible.value = false; + }); + } + }); +} diff --git a/src/views/system/user/role/permission-dialog.vue b/src/views/system/user/role/permission-dialog.vue deleted file mode 100644 index e6172b1..0000000 --- a/src/views/system/user/role/permission-dialog.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - - - diff --git a/src/views/system/user/role/permission-example.vue b/src/views/system/user/role/permission-example.vue deleted file mode 100644 index 7cfc634..0000000 --- a/src/views/system/user/role/permission-example.vue +++ /dev/null @@ -1,195 +0,0 @@ - - - - - diff --git a/src/views/system/user/role/render.vue b/src/views/system/user/role/render.vue deleted file mode 100644 index cbe703f..0000000 --- a/src/views/system/user/role/render.vue +++ /dev/null @@ -1,588 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/views/system/user/role/selectUser.vue b/src/views/system/user/role/selectUser.vue index 7ff0fe3..126e529 100644 --- a/src/views/system/user/role/selectUser.vue +++ b/src/views/system/user/role/selectUser.vue @@ -1,6 +1,6 @@ - - - diff --git a/src/views/system/user/user/components/DetailsDialog.vue b/src/views/system/user/user/components/DetailsDialog.vue new file mode 100644 index 0000000..ec1dce0 --- /dev/null +++ b/src/views/system/user/user/components/DetailsDialog.vue @@ -0,0 +1,122 @@ + + + diff --git a/src/views/system/user/user/components/GoogleCodeDialog.vue b/src/views/system/user/user/components/GoogleCodeDialog.vue new file mode 100644 index 0000000..1954af1 --- /dev/null +++ b/src/views/system/user/user/components/GoogleCodeDialog.vue @@ -0,0 +1,101 @@ + + + diff --git a/src/views/system/user/user/components/MyCustomForm.vue b/src/views/system/user/user/components/MyCustomForm.vue new file mode 100644 index 0000000..95bf86f --- /dev/null +++ b/src/views/system/user/user/components/MyCustomForm.vue @@ -0,0 +1,44 @@ + + + + \ No newline at end of file diff --git a/src/views/system/user/user/index.vue b/src/views/system/user/user/index.vue index 1551060..7689f07 100644 --- a/src/views/system/user/user/index.vue +++ b/src/views/system/user/user/index.vue @@ -1,450 +1,593 @@ - - - - \ No newline at end of file +}; + +getDeptTree(); +getList(); + diff --git a/vite.config.js.timestamp-1757468331223-0fc47cc4b54.mjs b/vite.config.js.timestamp-1757468331223-0fc47cc4b54.mjs new file mode 100644 index 0000000..9bb728f --- /dev/null +++ b/vite.config.js.timestamp-1757468331223-0fc47cc4b54.mjs @@ -0,0 +1,151 @@ +// vite.config.js +import { defineConfig, loadEnv } from "file:///E:/project/gameapi-client/node_modules/vite/dist/node/index.js"; +import path2 from "path"; + +// vite/plugins/index.js +import vue from "file:///E:/project/gameapi-client/node_modules/@vitejs/plugin-vue/dist/index.mjs"; + +// vite/plugins/auto-import.js +import autoImport from "file:///E:/project/gameapi-client/node_modules/unplugin-auto-import/dist/vite.js"; +function createAutoImport() { + return autoImport({ + imports: [ + "vue", + "vue-router", + "pinia" + ], + dts: false + }); +} + +// vite/plugins/svg-icon.js +import { createSvgIconsPlugin } from "file:///E:/project/gameapi-client/node_modules/vite-plugin-svg-icons/dist/index.mjs"; +import path from "path"; +function createSvgIcon(isBuild) { + return createSvgIconsPlugin({ + iconDirs: [path.resolve(process.cwd(), "src/assets/icons/svg")], + symbolId: "icon-[dir]-[name]", + svgoOptions: isBuild + }); +} + +// vite/plugins/compression.js +import compression from "file:///E:/project/gameapi-client/node_modules/vite-plugin-compression/dist/index.mjs"; +function createCompression(env) { + const { VITE_BUILD_COMPRESS } = env; + const plugin = []; + if (VITE_BUILD_COMPRESS) { + const compressList = VITE_BUILD_COMPRESS.split(","); + if (compressList.includes("gzip")) { + plugin.push( + compression({ + ext: ".gz", + deleteOriginFile: false + }) + ); + } + if (compressList.includes("brotli")) { + plugin.push( + compression({ + ext: ".br", + algorithm: "brotliCompress", + deleteOriginFile: false + }) + ); + } + } + return plugin; +} + +// vite/plugins/setup-extend.js +import setupExtend from "file:///E:/project/gameapi-client/node_modules/unplugin-vue-setup-extend-plus/dist/vite.js"; +function createSetupExtend() { + return setupExtend({}); +} + +// vite/plugins/index.js +function createVitePlugins(viteEnv, isBuild = false) { + const vitePlugins = [vue()]; + vitePlugins.push(createAutoImport()); + vitePlugins.push(createSetupExtend()); + vitePlugins.push(createSvgIcon(isBuild)); + isBuild && vitePlugins.push(...createCompression(viteEnv)); + return vitePlugins; +} + +// vite.config.js +var __vite_injected_original_dirname = "E:\\project\\gameapi-client"; +var vite_config_default = defineConfig(({ mode, command }) => { + const env = loadEnv(mode, process.cwd()); + const { VITE_APP_ENV } = env; + const buildTime = (/* @__PURE__ */ new Date()).getTime(); + return { + base: VITE_APP_ENV === "production" ? "/" : "/", + plugins: [ + ...createVitePlugins(env, command === "build") + ], + resolve: { + alias: { + // 设置路径 + "~": path2.resolve(__vite_injected_original_dirname, "./"), + // 设置别名 + "@": path2.resolve(__vite_injected_original_dirname, "./src") + }, + extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"] + }, + // vite 相关配置 + server: { + port: 80, + host: true, + open: true, + proxy: { + "/dev-api": { + target: "http://192.168.50.233:9080", + // target: 'http://192.168.50.11:9080', + // target: 'http://192.168.50.178:8080', + // target: 'http://192.168.50.99:8080', + changeOrigin: true, + rewrite: (p) => p.replace(/^\/dev-api/, "") + } + } + // proxy: { + // '/ff-api': { + // target: 'https://apiadmin.tt-gaming.com', // 线上接口地址 + // changeOrigin: true, // 是否允许跨域 + // pathRewrite: { + // '^/ff-api': '' // 如果你需要去掉前缀,例如将 /api/xxx 替换为 /xxx + // } + // } + // } + }, + css: { + postcss: { + plugins: [ + { + postcssPlugin: "internal:charset-removal", + AtRule: { + charset: (atRule) => { + if (atRule.name === "charset") { + atRule.remove(); + } + } + } + } + ] + } + }, + build: { + rollupOptions: { + output: { + entryFileNames: "assets/[name].[hash].js", + chunkFileNames: "assets/[name].[hash].js", + assetFileNames: "assets/[name].[hash].[ext]" + } + } + } + }; +}); +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiLCAidml0ZS9wbHVnaW5zL2luZGV4LmpzIiwgInZpdGUvcGx1Z2lucy9hdXRvLWltcG9ydC5qcyIsICJ2aXRlL3BsdWdpbnMvc3ZnLWljb24uanMiLCAidml0ZS9wbHVnaW5zL2NvbXByZXNzaW9uLmpzIiwgInZpdGUvcGx1Z2lucy9zZXR1cC1leHRlbmQuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFxwcm9qZWN0XFxcXGdhbWVhcGktY2xpZW50XCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJFOlxcXFxwcm9qZWN0XFxcXGdhbWVhcGktY2xpZW50XFxcXHZpdGUuY29uZmlnLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9FOi9wcm9qZWN0L2dhbWVhcGktY2xpZW50L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnLCBsb2FkRW52IH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcclxuaW1wb3J0IGNyZWF0ZVZpdGVQbHVnaW5zIGZyb20gJy4vdml0ZS9wbHVnaW5zJ1xyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoKHsgbW9kZSwgY29tbWFuZCB9KSA9PiB7XHJcbiAgIGNvbnN0IGVudiA9IGxvYWRFbnYobW9kZSwgcHJvY2Vzcy5jd2QoKSlcclxuICAgY29uc3QgeyBWSVRFX0FQUF9FTlYgfSA9IGVudlxyXG4gICBjb25zdCBidWlsZFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKVxyXG4gICByZXR1cm4ge1xyXG4gICAgICBiYXNlOiBWSVRFX0FQUF9FTlYgPT09ICdwcm9kdWN0aW9uJyA/ICcvJyA6ICcvJyxcclxuICAgICAgcGx1Z2luczogW1xyXG4gICAgICAgICAuLi5jcmVhdGVWaXRlUGx1Z2lucyhlbnYsIGNvbW1hbmQgPT09ICdidWlsZCcpLFxyXG4gICAgICBdLFxyXG4gICAgICByZXNvbHZlOiB7XHJcbiAgICAgICAgIGFsaWFzOiB7XHJcbiAgICAgICAgICAgIC8vIFx1OEJCRVx1N0Y2RVx1OERFRlx1NUY4NFxyXG4gICAgICAgICAgICAnfic6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLycpLFxyXG4gICAgICAgICAgICAvLyBcdThCQkVcdTdGNkVcdTUyMkJcdTU0MERcclxuICAgICAgICAgICAgJ0AnOiBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi9zcmMnKVxyXG4gICAgICAgICB9LFxyXG4gICAgICAgICBleHRlbnNpb25zOiBbJy5tanMnLCAnLmpzJywgJy50cycsICcuanN4JywgJy50c3gnLCAnLmpzb24nLCAnLnZ1ZSddXHJcbiAgICAgIH0sXHJcbiAgICAgIC8vIHZpdGUgXHU3NkY4XHU1MTczXHU5MTREXHU3RjZFXHJcbiAgICAgIHNlcnZlcjoge1xyXG4gICAgICAgICBwb3J0OiA4MCxcclxuICAgICAgICAgaG9zdDogdHJ1ZSxcclxuICAgICAgICAgb3BlbjogdHJ1ZSxcclxuICAgICAgICAgcHJveHk6IHtcclxuICAgICAgICAgICAgJy9kZXYtYXBpJzoge1xyXG4gICAgICAgICAgICAgICB0YXJnZXQ6ICdodHRwOi8vMTkyLjE2OC41MC4yMzM6OTA4MCcsXHJcbiAgICAgICAgICAgICAgIC8vIHRhcmdldDogJ2h0dHA6Ly8xOTIuMTY4LjUwLjExOjkwODAnLFxyXG4gICAgICAgICAgICAgIC8vICB0YXJnZXQ6ICdodHRwOi8vMTkyLjE2OC41MC4xNzg6ODA4MCcsXHJcbiAgICAgICAgICAgICAgIC8vIHRhcmdldDogJ2h0dHA6Ly8xOTIuMTY4LjUwLjk5OjgwODAnLFxyXG4gICAgICAgICAgICAgICBjaGFuZ2VPcmlnaW46IHRydWUsXHJcbiAgICAgICAgICAgICAgIHJld3JpdGU6IChwKSA9PiBwLnJlcGxhY2UoL15cXC9kZXYtYXBpLywgJycpXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgfSxcclxuICAgICAgICAvLyAgcHJveHk6IHtcclxuICAgICAgICAvLyAgICAgJy9mZi1hcGknOiB7XHJcbiAgICAgICAgLy8gICAgICAgIHRhcmdldDogJ2h0dHBzOi8vYXBpYWRtaW4udHQtZ2FtaW5nLmNvbScsIC8vIFx1N0VCRlx1NEUwQVx1NjNBNVx1NTNFM1x1NTczMFx1NTc0MFxyXG4gICAgICAgIC8vICAgICAgICBjaGFuZ2VPcmlnaW46IHRydWUsIC8vIFx1NjYyRlx1NTQyNlx1NTE0MVx1OEJCOFx1OERFOFx1NTdERlxyXG4gICAgICAgIC8vICAgICAgICBwYXRoUmV3cml0ZToge1xyXG4gICAgICAgIC8vICAgICAgICAgICAnXi9mZi1hcGknOiAnJyAvLyBcdTU5ODJcdTY3OUNcdTRGNjBcdTk3MDBcdTg5ODFcdTUzQkJcdTYzODlcdTUyNERcdTdGMDBcdUZGMENcdTRGOEJcdTU5ODJcdTVDMDYgL2FwaS94eHggXHU2NkZGXHU2MzYyXHU0RTNBIC94eHhcclxuICAgICAgICAvLyAgICAgICAgfVxyXG4gICAgICAgIC8vICAgICB9XHJcbiAgICAgICAgLy8gIH1cclxuICAgICAgfSxcclxuICAgICAgY3NzOiB7XHJcbiAgICAgICAgIHBvc3Rjc3M6IHtcclxuICAgICAgICAgICAgcGx1Z2luczogW1xyXG4gICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgIHBvc3Rjc3NQbHVnaW46ICdpbnRlcm5hbDpjaGFyc2V0LXJlbW92YWwnLFxyXG4gICAgICAgICAgICAgICAgICBBdFJ1bGU6IHtcclxuICAgICAgICAgICAgICAgICAgICAgY2hhcnNldDogKGF0UnVsZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXRSdWxlLm5hbWUgPT09ICdjaGFyc2V0Jykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBhdFJ1bGUucmVtb3ZlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgXVxyXG4gICAgICAgICB9XHJcbiAgICAgIH0sXHJcbiAgICAgIGJ1aWxkOiB7XHJcbiAgICAgICAgIHJvbGx1cE9wdGlvbnM6IHtcclxuICAgICAgICAgICAgb3V0cHV0OiB7XHJcbiAgICAgICAgICAgICAgIGVudHJ5RmlsZU5hbWVzOiAnYXNzZXRzL1tuYW1lXS5baGFzaF0uanMnLFxyXG4gICAgICAgICAgICAgICBjaHVua0ZpbGVOYW1lczogJ2Fzc2V0cy9bbmFtZV0uW2hhc2hdLmpzJyxcclxuICAgICAgICAgICAgICAgYXNzZXRGaWxlTmFtZXM6ICdhc3NldHMvW25hbWVdLltoYXNoXS5bZXh0XSdcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgfVxyXG59KVxyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkU6XFxcXHByb2plY3RcXFxcZ2FtZWFwaS1jbGllbnRcXFxcdml0ZVxcXFxwbHVnaW5zXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJFOlxcXFxwcm9qZWN0XFxcXGdhbWVhcGktY2xpZW50XFxcXHZpdGVcXFxccGx1Z2luc1xcXFxpbmRleC5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRTovcHJvamVjdC9nYW1lYXBpLWNsaWVudC92aXRlL3BsdWdpbnMvaW5kZXguanNcIjtpbXBvcnQgdnVlIGZyb20gJ0B2aXRlanMvcGx1Z2luLXZ1ZSdcclxuXHJcbmltcG9ydCBjcmVhdGVBdXRvSW1wb3J0IGZyb20gJy4vYXV0by1pbXBvcnQnXHJcbmltcG9ydCBjcmVhdGVTdmdJY29uIGZyb20gJy4vc3ZnLWljb24nXHJcbmltcG9ydCBjcmVhdGVDb21wcmVzc2lvbiBmcm9tICcuL2NvbXByZXNzaW9uJ1xyXG5pbXBvcnQgY3JlYXRlU2V0dXBFeHRlbmQgZnJvbSAnLi9zZXR1cC1leHRlbmQnXHJcblxyXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBjcmVhdGVWaXRlUGx1Z2lucyh2aXRlRW52LCBpc0J1aWxkID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IHZpdGVQbHVnaW5zID0gW3Z1ZSgpXVxyXG4gICAgdml0ZVBsdWdpbnMucHVzaChjcmVhdGVBdXRvSW1wb3J0KCkpXHJcblx0dml0ZVBsdWdpbnMucHVzaChjcmVhdGVTZXR1cEV4dGVuZCgpKVxyXG4gICAgdml0ZVBsdWdpbnMucHVzaChjcmVhdGVTdmdJY29uKGlzQnVpbGQpKVxyXG5cdGlzQnVpbGQgJiYgdml0ZVBsdWdpbnMucHVzaCguLi5jcmVhdGVDb21wcmVzc2lvbih2aXRlRW52KSlcclxuICAgIHJldHVybiB2aXRlUGx1Z2luc1xyXG59XHJcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiRTpcXFxccHJvamVjdFxcXFxnYW1lYXBpLWNsaWVudFxcXFx2aXRlXFxcXHBsdWdpbnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkU6XFxcXHByb2plY3RcXFxcZ2FtZWFwaS1jbGllbnRcXFxcdml0ZVxcXFxwbHVnaW5zXFxcXGF1dG8taW1wb3J0LmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9FOi9wcm9qZWN0L2dhbWVhcGktY2xpZW50L3ZpdGUvcGx1Z2lucy9hdXRvLWltcG9ydC5qc1wiO2ltcG9ydCBhdXRvSW1wb3J0IGZyb20gJ3VucGx1Z2luLWF1dG8taW1wb3J0L3ZpdGUnXHJcblxyXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBjcmVhdGVBdXRvSW1wb3J0KCkge1xyXG4gICAgcmV0dXJuIGF1dG9JbXBvcnQoe1xyXG4gICAgICAgIGltcG9ydHM6IFtcclxuICAgICAgICAgICAgJ3Z1ZScsXHJcbiAgICAgICAgICAgICd2dWUtcm91dGVyJyxcclxuICAgICAgICAgICAgJ3BpbmlhJ1xyXG4gICAgICAgIF0sXHJcbiAgICAgICAgZHRzOiBmYWxzZVxyXG4gICAgfSlcclxufVxyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkU6XFxcXHByb2plY3RcXFxcZ2FtZWFwaS1jbGllbnRcXFxcdml0ZVxcXFxwbHVnaW5zXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJFOlxcXFxwcm9qZWN0XFxcXGdhbWVhcGktY2xpZW50XFxcXHZpdGVcXFxccGx1Z2luc1xcXFxzdmctaWNvbi5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRTovcHJvamVjdC9nYW1lYXBpLWNsaWVudC92aXRlL3BsdWdpbnMvc3ZnLWljb24uanNcIjtpbXBvcnQgeyBjcmVhdGVTdmdJY29uc1BsdWdpbiB9IGZyb20gJ3ZpdGUtcGx1Z2luLXN2Zy1pY29ucydcclxuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGNyZWF0ZVN2Z0ljb24oaXNCdWlsZCkge1xyXG4gICAgcmV0dXJuIGNyZWF0ZVN2Z0ljb25zUGx1Z2luKHtcclxuXHRcdGljb25EaXJzOiBbcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksICdzcmMvYXNzZXRzL2ljb25zL3N2ZycpXSxcclxuICAgICAgICBzeW1ib2xJZDogJ2ljb24tW2Rpcl0tW25hbWVdJyxcclxuICAgICAgICBzdmdvT3B0aW9uczogaXNCdWlsZFxyXG4gICAgfSlcclxufVxyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkU6XFxcXHByb2plY3RcXFxcZ2FtZWFwaS1jbGllbnRcXFxcdml0ZVxcXFxwbHVnaW5zXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJFOlxcXFxwcm9qZWN0XFxcXGdhbWVhcGktY2xpZW50XFxcXHZpdGVcXFxccGx1Z2luc1xcXFxjb21wcmVzc2lvbi5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRTovcHJvamVjdC9nYW1lYXBpLWNsaWVudC92aXRlL3BsdWdpbnMvY29tcHJlc3Npb24uanNcIjtpbXBvcnQgY29tcHJlc3Npb24gZnJvbSAndml0ZS1wbHVnaW4tY29tcHJlc3Npb24nXHJcblxyXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBjcmVhdGVDb21wcmVzc2lvbihlbnYpIHtcclxuICAgIGNvbnN0IHsgVklURV9CVUlMRF9DT01QUkVTUyB9ID0gZW52XHJcbiAgICBjb25zdCBwbHVnaW4gPSBbXVxyXG4gICAgaWYgKFZJVEVfQlVJTERfQ09NUFJFU1MpIHtcclxuICAgICAgICBjb25zdCBjb21wcmVzc0xpc3QgPSBWSVRFX0JVSUxEX0NPTVBSRVNTLnNwbGl0KCcsJylcclxuICAgICAgICBpZiAoY29tcHJlc3NMaXN0LmluY2x1ZGVzKCdnemlwJykpIHtcclxuICAgICAgICAgICAgLy8gaHR0cDovL2RvYy5ydW95aS52aXAvcnVveWktdnVlL290aGVyL2ZhcS5odG1sI1x1NEY3Rlx1NzUyOGd6aXBcdTg5RTNcdTUzOEJcdTdGMjlcdTk3NTlcdTYwMDFcdTY1ODdcdTRFRjZcclxuICAgICAgICAgICAgcGx1Z2luLnB1c2goXHJcbiAgICAgICAgICAgICAgICBjb21wcmVzc2lvbih7XHJcbiAgICAgICAgICAgICAgICAgICAgZXh0OiAnLmd6JyxcclxuICAgICAgICAgICAgICAgICAgICBkZWxldGVPcmlnaW5GaWxlOiBmYWxzZVxyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY29tcHJlc3NMaXN0LmluY2x1ZGVzKCdicm90bGknKSkge1xyXG4gICAgICAgICAgICBwbHVnaW4ucHVzaChcclxuICAgICAgICAgICAgICAgIGNvbXByZXNzaW9uKHtcclxuICAgICAgICAgICAgICAgICAgICBleHQ6ICcuYnInLFxyXG4gICAgICAgICAgICAgICAgICAgIGFsZ29yaXRobTogJ2Jyb3RsaUNvbXByZXNzJyxcclxuICAgICAgICAgICAgICAgICAgICBkZWxldGVPcmlnaW5GaWxlOiBmYWxzZVxyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBwbHVnaW5cclxufVxyXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIkU6XFxcXHByb2plY3RcXFxcZ2FtZWFwaS1jbGllbnRcXFxcdml0ZVxcXFxwbHVnaW5zXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJFOlxcXFxwcm9qZWN0XFxcXGdhbWVhcGktY2xpZW50XFxcXHZpdGVcXFxccGx1Z2luc1xcXFxzZXR1cC1leHRlbmQuanNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0U6L3Byb2plY3QvZ2FtZWFwaS1jbGllbnQvdml0ZS9wbHVnaW5zL3NldHVwLWV4dGVuZC5qc1wiO2ltcG9ydCBzZXR1cEV4dGVuZCBmcm9tICd1bnBsdWdpbi12dWUtc2V0dXAtZXh0ZW5kLXBsdXMvdml0ZSdcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGNyZWF0ZVNldHVwRXh0ZW5kKCkge1xyXG4gICAgcmV0dXJuIHNldHVwRXh0ZW5kKHt9KVxyXG59XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBbVEsU0FBUyxjQUFjLGVBQWU7QUFDelMsT0FBT0EsV0FBVTs7O0FDRGlSLE9BQU8sU0FBUzs7O0FDQUosT0FBTyxnQkFBZ0I7QUFFdFQsU0FBUixtQkFBb0M7QUFDdkMsU0FBTyxXQUFXO0FBQUEsSUFDZCxTQUFTO0FBQUEsTUFDTDtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsSUFDSjtBQUFBLElBQ0EsS0FBSztBQUFBLEVBQ1QsQ0FBQztBQUNMOzs7QUNYd1MsU0FBUyw0QkFBNEI7QUFDN1UsT0FBTyxVQUFVO0FBRUYsU0FBUixjQUErQixTQUFTO0FBQzNDLFNBQU8scUJBQXFCO0FBQUEsSUFDOUIsVUFBVSxDQUFDLEtBQUssUUFBUSxRQUFRLElBQUksR0FBRyxzQkFBc0IsQ0FBQztBQUFBLElBQ3hELFVBQVU7QUFBQSxJQUNWLGFBQWE7QUFBQSxFQUNqQixDQUFDO0FBQ0w7OztBQ1Q4UyxPQUFPLGlCQUFpQjtBQUV2VCxTQUFSLGtCQUFtQyxLQUFLO0FBQzNDLFFBQU0sRUFBRSxvQkFBb0IsSUFBSTtBQUNoQyxRQUFNLFNBQVMsQ0FBQztBQUNoQixNQUFJLHFCQUFxQjtBQUNyQixVQUFNLGVBQWUsb0JBQW9CLE1BQU0sR0FBRztBQUNsRCxRQUFJLGFBQWEsU0FBUyxNQUFNLEdBQUc7QUFFL0IsYUFBTztBQUFBLFFBQ0gsWUFBWTtBQUFBLFVBQ1IsS0FBSztBQUFBLFVBQ0wsa0JBQWtCO0FBQUEsUUFDdEIsQ0FBQztBQUFBLE1BQ0w7QUFBQSxJQUNKO0FBQ0EsUUFBSSxhQUFhLFNBQVMsUUFBUSxHQUFHO0FBQ2pDLGFBQU87QUFBQSxRQUNILFlBQVk7QUFBQSxVQUNSLEtBQUs7QUFBQSxVQUNMLFdBQVc7QUFBQSxVQUNYLGtCQUFrQjtBQUFBLFFBQ3RCLENBQUM7QUFBQSxNQUNMO0FBQUEsSUFDSjtBQUFBLEVBQ0o7QUFDQSxTQUFPO0FBQ1g7OztBQzNCZ1QsT0FBTyxpQkFBaUI7QUFFelQsU0FBUixvQkFBcUM7QUFDeEMsU0FBTyxZQUFZLENBQUMsQ0FBQztBQUN6Qjs7O0FKR2UsU0FBUixrQkFBbUMsU0FBUyxVQUFVLE9BQU87QUFDaEUsUUFBTSxjQUFjLENBQUMsSUFBSSxDQUFDO0FBQzFCLGNBQVksS0FBSyxpQkFBaUIsQ0FBQztBQUN0QyxjQUFZLEtBQUssa0JBQWtCLENBQUM7QUFDakMsY0FBWSxLQUFLLGNBQWMsT0FBTyxDQUFDO0FBQzFDLGFBQVcsWUFBWSxLQUFLLEdBQUcsa0JBQWtCLE9BQU8sQ0FBQztBQUN0RCxTQUFPO0FBQ1g7OztBRGRBLElBQU0sbUNBQW1DO0FBR3pDLElBQU8sc0JBQVEsYUFBYSxDQUFDLEVBQUUsTUFBTSxRQUFRLE1BQU07QUFDaEQsUUFBTSxNQUFNLFFBQVEsTUFBTSxRQUFRLElBQUksQ0FBQztBQUN2QyxRQUFNLEVBQUUsYUFBYSxJQUFJO0FBQ3pCLFFBQU0sYUFBWSxvQkFBSSxLQUFLLEdBQUUsUUFBUTtBQUNyQyxTQUFPO0FBQUEsSUFDSixNQUFNLGlCQUFpQixlQUFlLE1BQU07QUFBQSxJQUM1QyxTQUFTO0FBQUEsTUFDTixHQUFHLGtCQUFrQixLQUFLLFlBQVksT0FBTztBQUFBLElBQ2hEO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDTixPQUFPO0FBQUE7QUFBQSxRQUVKLEtBQUtDLE1BQUssUUFBUSxrQ0FBVyxJQUFJO0FBQUE7QUFBQSxRQUVqQyxLQUFLQSxNQUFLLFFBQVEsa0NBQVcsT0FBTztBQUFBLE1BQ3ZDO0FBQUEsTUFDQSxZQUFZLENBQUMsUUFBUSxPQUFPLE9BQU8sUUFBUSxRQUFRLFNBQVMsTUFBTTtBQUFBLElBQ3JFO0FBQUE7QUFBQSxJQUVBLFFBQVE7QUFBQSxNQUNMLE1BQU07QUFBQSxNQUNOLE1BQU07QUFBQSxNQUNOLE1BQU07QUFBQSxNQUNOLE9BQU87QUFBQSxRQUNKLFlBQVk7QUFBQSxVQUNULFFBQVE7QUFBQTtBQUFBO0FBQUE7QUFBQSxVQUlSLGNBQWM7QUFBQSxVQUNkLFNBQVMsQ0FBQyxNQUFNLEVBQUUsUUFBUSxjQUFjLEVBQUU7QUFBQSxRQUM3QztBQUFBLE1BQ0g7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQVVIO0FBQUEsSUFDQSxLQUFLO0FBQUEsTUFDRixTQUFTO0FBQUEsUUFDTixTQUFTO0FBQUEsVUFDTjtBQUFBLFlBQ0csZUFBZTtBQUFBLFlBQ2YsUUFBUTtBQUFBLGNBQ0wsU0FBUyxDQUFDLFdBQVc7QUFDbEIsb0JBQUksT0FBTyxTQUFTLFdBQVc7QUFDNUIseUJBQU8sT0FBTztBQUFBLGdCQUNqQjtBQUFBLGNBQ0g7QUFBQSxZQUNIO0FBQUEsVUFDSDtBQUFBLFFBQ0g7QUFBQSxNQUNIO0FBQUEsSUFDSDtBQUFBLElBQ0EsT0FBTztBQUFBLE1BQ0osZUFBZTtBQUFBLFFBQ1osUUFBUTtBQUFBLFVBQ0wsZ0JBQWdCO0FBQUEsVUFDaEIsZ0JBQWdCO0FBQUEsVUFDaEIsZ0JBQWdCO0FBQUEsUUFDbkI7QUFBQSxNQUNIO0FBQUEsSUFDSDtBQUFBLEVBQ0g7QUFDSCxDQUFDOyIsCiAgIm5hbWVzIjogWyJwYXRoIiwgInBhdGgiXQp9Cg==