修改后台生成代码

dev_xd
haha 2025-05-21 23:13:05 +08:00
parent 95d37fab45
commit fc82ce3ef9
7 changed files with 412 additions and 342 deletions

View File

@ -8,6 +8,9 @@
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/>
<script>
window.yanzhuAppTitle = "数字建安施工";
</script>
<link rel="icon" href="/favicon.ico" />
<title>数字建安施工</title>
<script
@ -217,5 +220,8 @@
</div>
</div>
<script type="module" src="/src/main.js"></script>
<script>
window.document.body.title = window.yanzhuAppTitle;
</script>
</body>
</html>

View File

@ -0,0 +1,55 @@
const fs = require("fs");
const path = require("path");
const config = [
{
name: "app1",
title: "建安施工管理平台",
dirPath: "app1",
},
{
name: "app2",
title: "数字项管+",
dirPath: "app2",
},
];
config.forEach((item) => {
// 在 dist 目录下创建 app 目录
const appDirPath = path.join(__dirname, "dist", item.dirPath);
fs.mkdir(appDirPath, { recursive: true }, (err) => {
if (err) {
console.error("创建目录时出错:", err);
return;
}
console.log("目录创建成功或已存在");
});
const xdAppPath = path.join(__dirname, "dist", "xd");
// 源文件路径
const sourceFilePath = path.join(xdAppPath, "index.html");
// 目标文件路径
const targetFilePath = path.join(appDirPath, "index.html");
// 读取源文件内容
fs.readFile(sourceFilePath, "utf8", (err, data) => {
if (err) {
console.error("读取文件时出错:", err);
return;
}
// 替换文本
const newData = data
.replace(/数字建安施工/g, item.title)
.replaceAll(`src="./`, `src = "/xd/`)
.replaceAll(`href="./`, `href = "/xd/`);
// 将替换后的内容写入目标文件
fs.writeFile(targetFilePath, newData, "utf8", (err) => {
if (err) {
console.error("写入文件时出错:", err);
return;
}
console.log("文件复制并替换成功");
});
});
});

View File

@ -8,8 +8,9 @@
"scripts": {
"dev": "vite",
"dev:prod": "vite --mode production",
"build:prod": "vite build",
"build:prod": "vite build && npm run pkg",
"build:stage": "vite build --mode staging",
"pkg":"node make.cjs",
"preview": "vite preview"
},
"repository": {

View File

@ -1,16 +1,16 @@
<template>
<div class="sidebar-logo-container" :class="{ 'collapse': collapse }" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
</router-link>
</transition>
</div>
<div class="sidebar-logo-container" :class="{ 'collapse': collapse }" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
</router-link>
</transition>
</div>
</template>
<script setup>
@ -19,63 +19,63 @@ import logo from '@/assets/logo/logo.png'
import useSettingsStore from '@/store/modules/settings'
defineProps({
collapse: {
type: Boolean,
required: true
}
collapse: {
type: Boolean,
required: true,
},
})
const title = import.meta.env.VITE_APP_TITLE;
const settingsStore = useSettingsStore();
const sideTheme = computed(() => settingsStore.sideTheme);
const title = window.yanzhuAppTitle
const settingsStore = useSettingsStore()
const sideTheme = computed(() => settingsStore.sideTheme)
</script>
<style lang="scss" scoped>
.sidebarLogoFade-enter-active {
transition: opacity 1.5s;
transition: opacity 1.5s;
}
.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
opacity: 0;
opacity: 0;
}
.sidebar-logo-container {
position: relative;
width: 100%;
height: 50px;
line-height: 50px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo-link {
height: 100%;
position: relative;
width: 100%;
height: 50px;
line-height: 50px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
& .sidebar-logo-link {
height: 100%;
width: 100%;
& .sidebar-logo {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
}
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
</style>

View File

@ -2,11 +2,11 @@ export default {
/**
* 网页标题
*/
title: import.meta.env.VITE_APP_TITLE,
title: window.yanzhuAppTitle,
/**
* 侧边栏主题 深色主题theme-dark浅色主题theme-light
*/
sideTheme: 'theme-dark',
sideTheme: "theme-dark",
/**
* 是否系统布局配置
*/
@ -43,5 +43,5 @@ export default {
* The default is only used in the production env
* If you want to also use it in dev, you can pass ['production', 'development']
*/
errorLog: 'production'
}
errorLog: "production",
};

View File

@ -1,289 +1,294 @@
<template>
<div class="login main-login">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">数字建安</h3>
<el-form-item prop="username" style="margin-top:60px;">
<el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="账号">
<template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码"
@keyup.enter="handleLogin">
<template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 63%"
@keyup.enter="handleLogin">
<template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
</el-input>
<div class="login-code">
<div class="login-code-bg"></div>
<img :src="codeUrl" @click="getCode" class="login-code-img" />
<div class="login main-login">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">{{title}}</h3>
<el-form-item prop="username" style="margin-top:60px;">
<el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="账号">
<template #prefix>
<svg-icon icon-class="user" class="el-input__icon input-icon" />
</template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码" @keyup.enter="handleLogin">
<template #prefix>
<svg-icon icon-class="password" class="el-input__icon input-icon" />
</template>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter="handleLogin">
<template #prefix>
<svg-icon icon-class="validCode" class="el-input__icon input-icon" />
</template>
</el-input>
<div class="login-code">
<div class="login-code-bg"></div>
<img :src="codeUrl" @click="getCode" class="login-code-img" />
</div>
</el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;"></el-checkbox>
<el-form-item style="width:100%;">
<el-button :loading="loading" class="btn-login" size="large" type="primary" style="width:100%;" @click.prevent="handleLogin">
<span v-if="!loading"> </span>
<span v-else> ...</span>
</el-button>
<div style="float: right;" v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link>
</div>
</el-form-item>
<div class="login-form-bg"></div>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2023-2024 陕西研筑信息科技有限公司 All Rights Reserved.</span>
</div>
</el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;"></el-checkbox>
<el-form-item style="width:100%;">
<el-button :loading="loading" class="btn-login" size="large" type="primary" style="width:100%;"
@click.prevent="handleLogin">
<span v-if="!loading"> </span>
<span v-else> ...</span>
</el-button>
<div style="float: right;" v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link>
</div>
</el-form-item>
<div class="login-form-bg"></div>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2023-2024 陕西研筑信息科技有限公司 All Rights Reserved.</span>
</div>
</div>
</template>
<script setup>
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt";
import { getCodeImg } from '@/api/login'
import Cookies from 'js-cookie'
import { encrypt, decrypt } from '@/utils/jsencrypt'
import useUserStore from '@/store/modules/user'
const userStore = useUserStore()
const router = useRouter();
const router = useRouter()
const route = useRoute()
const { proxy } = getCurrentInstance();
const { proxy } = getCurrentInstance()
let title = ref('系统登录')
title.value = window.yanzhuAppTitle
const loginForm = ref({
username: "",
password: "",
rememberMe: false,
code: "",
uuid: ""
});
username: '',
password: '',
rememberMe: false,
code: '',
uuid: '',
})
const loginRules = {
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
code: [{ required: true, trigger: "change", message: "请输入验证码" }]
};
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }],
code: [{ required: true, trigger: 'change', message: '请输入验证码' }],
}
const codeUrl = ref("");
const loading = ref(false);
const codeUrl = ref('')
const loading = ref(false)
//
const captchaEnabled = ref(true);
const captchaEnabled = ref(true)
//
const register = ref(false);
const redirect = ref(undefined);
const register = ref(false)
const redirect = ref(undefined)
function handleLogin() {
proxy.$refs.loginRef.validate(valid => {
if (valid) {
loading.value = true;
// cookie
if (loginForm.value.rememberMe) {
Cookies.set("username", loginForm.value.username, { expires: 30 });
Cookies.set("password", encrypt(loginForm.value.password), { expires: 30 });
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
} else {
//
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove("rememberMe");
}
// action
userStore.login(loginForm.value).then(() => {
if (route.query?.redirect) {
location.href = route.query.redirect;
} else {
router.push({ path: "/" });
proxy.$refs.loginRef.validate((valid) => {
if (valid) {
loading.value = true
// cookie
if (loginForm.value.rememberMe) {
Cookies.set('username', loginForm.value.username, { expires: 30 })
Cookies.set('password', encrypt(loginForm.value.password), { expires: 30 })
Cookies.set('rememberMe', loginForm.value.rememberMe, { expires: 30 })
} else {
//
Cookies.remove('username')
Cookies.remove('password')
Cookies.remove('rememberMe')
}
// action
userStore
.login(loginForm.value)
.then(() => {
if (route.query?.redirect) {
location.href = route.query.redirect
} else {
router.push({ path: '/' })
}
})
.catch(() => {
loading.value = false
//
if (captchaEnabled.value) {
getCode()
}
})
}
}).catch(() => {
loading.value = false;
//
if (captchaEnabled.value) {
getCode();
}
});
}
});
})
}
function getCode() {
getCodeImg().then(res => {
captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (captchaEnabled.value) {
codeUrl.value = "data:image/gif;base64," + res.img;
loginForm.value.uuid = res.uuid;
}
});
getCodeImg().then((res) => {
captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled
if (captchaEnabled.value) {
codeUrl.value = 'data:image/gif;base64,' + res.img
loginForm.value.uuid = res.uuid
}
})
}
function getCookie() {
const username = Cookies.get("username");
const password = Cookies.get("password");
const rememberMe = Cookies.get("rememberMe");
loginForm.value = {
username: username === undefined ? loginForm.value.username : username,
password: password === undefined ? loginForm.value.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
};
const username = Cookies.get('username')
const password = Cookies.get('password')
const rememberMe = Cookies.get('rememberMe')
loginForm.value = {
username: username === undefined ? loginForm.value.username : username,
password: password === undefined ? loginForm.value.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
}
}
getCode();
getCookie();
getCode()
getCookie()
</script>
<style lang='scss'>
.login.main-login {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url("../assets/images/loginbg.jpeg");
background-size: cover;
position: relative;
.title {
margin: 0px auto 30px auto;
text-align: center;
color: #707070;
font-size: 28px;
}
.login-form-bg {
background-image: url("../assets/images/loginbg3.png");
position: absolute;
top: 0%;
width: 80%;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-position: center;
background-size: 100%;
background-repeat: no-repeat;
filter: opacity(0.8);
}
.login-form {
border-radius: 6px;
background-image: url("../assets/images/loginbg2.png");
background-size: 100% 100%;
width: 420px;
padding: 50px;
position: absolute;
height: 560px;
right: 10%;
.el-form-item {
position: relative;
z-index: 10;
}
.title {
position: relative;
top: -68px;
color: #336699;
font-weight: bold;
}
.el-form-item--default {
margin-bottom: 40px;
}
.el-input {
height: 30px;
.el-input__wrapper {
background: #113356;
box-shadow: 0px 0px 0px 1px #1262b5;
border-radius: 15px;
.el-input__prefix-inner {
svg {
fill: #45C4DD;
}
}
}
input {
height: 30px;
color: #fff;
}
}
.input-icon {
height: 29px;
width: 14px;
margin-left: 0px;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
height: 30px;
float: right;
background-image: url('../assets/images/loginbg.jpeg');
background-size: cover;
position: relative;
.login-code-bg {
position: absolute;
background: #113356;
box-shadow: 0px 0px 0px 1px #1262b5;
width: 70px;
height: 30px;
left: 20px;
.title {
margin: 0px auto 30px auto;
text-align: center;
color: #707070;
font-size: 28px;
}
img {
position: relative;
z-index: 10;
cursor: pointer;
vertical-align: middle;
.login-form-bg {
background-image: url('../assets/images/loginbg3.png');
position: absolute;
top: 0%;
width: 80%;
height: 100%;
background-position: center;
background-size: 100%;
background-repeat: no-repeat;
filter: opacity(0.8);
}
}
.el-checkbox__inner {
background: #113356;
border: solid 1px #1262b5;
}
.login-form {
border-radius: 6px;
background-image: url('../assets/images/loginbg2.png');
background-size: 100% 100%;
width: 420px;
padding: 50px;
position: absolute;
height: 560px;
right: 10%;
.el-checkbox__input+.el-checkbox__label {
color: #aaa;
}
.el-form-item {
position: relative;
z-index: 10;
}
.el-checkbox__input.is-checked+.el-checkbox__label {
color: var(--el-checkbox-checked-text-color) !important;
}
.title {
position: relative;
top: -90px;
color: #336699;
font-weight: bold;
}
.btn-login {
background: #113356;
border: solid 1px #1262b5;
height: 36px;
line-height: 36px;
}
.el-form-item--default {
margin-bottom: 40px;
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.el-input {
height: 30px;
.login-code-img {
height: 30px;
padding-left: 12px;
}
.el-input__wrapper {
background: #113356;
box-shadow: 0px 0px 0px 1px #1262b5;
border-radius: 15px;
.el-input__prefix-inner {
svg {
fill: #45c4dd;
}
}
}
input {
height: 30px;
color: #fff;
}
}
.input-icon {
height: 29px;
width: 14px;
margin-left: 0px;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
height: 30px;
float: right;
position: relative;
.login-code-bg {
position: absolute;
background: #113356;
box-shadow: 0px 0px 0px 1px #1262b5;
width: 70px;
height: 30px;
left: 20px;
}
img {
position: relative;
z-index: 10;
cursor: pointer;
vertical-align: middle;
}
}
.el-checkbox__inner {
background: #113356;
border: solid 1px #1262b5;
}
.el-checkbox__input + .el-checkbox__label {
color: #aaa;
}
.el-checkbox__input.is-checked + .el-checkbox__label {
color: var(--el-checkbox-checked-text-color) !important;
}
.btn-login {
background: #113356;
border: solid 1px #1262b5;
height: 36px;
line-height: 36px;
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 30px;
padding-left: 12px;
}
}
</style>

View File

@ -1,27 +1,27 @@
import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import createVitePlugins from './vite/plugins'
import { defineConfig, loadEnv } from "vite";
import path from "path";
import createVitePlugins from "./vite/plugins";
// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd())
const { VITE_APP_ENV } = env
const env = loadEnv(mode, process.cwd());
const { VITE_APP_ENV } = env;
return {
// 部署生产环境和开发环境下的URL。
// 默认情况下vite 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
base: VITE_APP_ENV === 'production' ? '/xd/' : '/xd/',
plugins: createVitePlugins(env, command === 'build'),
base: VITE_APP_ENV === "production" ? "/xd/" : "/xd/",
plugins: createVitePlugins(env, command === "build"),
resolve: {
// https://cn.vitejs.dev/config/#resolve-alias
alias: {
// 设置路径
'~': path.resolve(__dirname, './'),
"~": path.resolve(__dirname, "./"),
// 设置别名
'@': path.resolve(__dirname, './src')
"@": path.resolve(__dirname, "./src"),
},
// https://cn.vitejs.dev/config/#resolve-extensions
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
},
// vite 相关配置
server: {
@ -30,56 +30,59 @@ export default defineConfig(({ mode, command }) => {
open: true,
proxy: {
"/prod-api": {
//target: "http://localhost:8080",
target: 'http://62.234.3.186',
changeOrigin: true,
pathRewrite: {
"^/prod-api": "/",
},
},
// https://cn.vitejs.dev/config/#server-proxy
'/dev-api': {
target: 'http://localhost:8080',
//target: "http://localhost:8080",
target: "http://62.234.3.186",
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '')
pathRewrite: {
"^/prod-api": "/",
},
},
'/statics': {
target: VITE_APP_ENV === 'production'?'http://62.234.3.186':`http://localhost:9300`,
// https://cn.vitejs.dev/config/#server-proxy
"/dev-api": {
target: "http://localhost:8080",
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, ""),
},
"/statics": {
target:
VITE_APP_ENV === "production"
? "http://62.234.3.186"
: `http://localhost:9300`,
//target: 'http://62.234.3.186',
changeOrigin: true,
pathRewrite: {
"^/statics": "/",
},
},
}
},
},
//fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file
css: {
postcss: {
plugins: [
{
postcssPlugin: 'internal:charset-removal',
postcssPlugin: "internal:charset-removal",
AtRule: {
charset: (atRule) => {
if (atRule.name === 'charset') {
if (atRule.name === "charset") {
atRule.remove();
}
}
}
}
]
}
},
},
},
],
},
},
optimizeDeps: {
include: ['@/lib/vform/designer.umd.js'] //此处路径必须跟main.js中import路径完全一致
},
build: {
include: ["@/lib/vform/designer.umd.js"], //此处路径必须跟main.js中import路径完全一致
},
build: {
outDir: "dist/xd/",
/* 其他build生产打包配置省略 */
//...
commonjsOptions: {
include: /node_modules|lib/ //这里记得把lib目录加进来否则生产打包会报错
}
}
}
})
include: /node_modules|lib/, //这里记得把lib目录加进来否则生产打包会报错
},
},
};
});