修改后台生成代码

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" name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/> />
<script>
window.yanzhuAppTitle = "数字建安施工";
</script>
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<title>数字建安施工</title> <title>数字建安施工</title>
<script <script
@ -217,5 +220,8 @@
</div> </div>
</div> </div>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.js"></script>
<script>
window.document.body.title = window.yanzhuAppTitle;
</script>
</body> </body>
</html> </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": { "scripts": {
"dev": "vite", "dev": "vite",
"dev:prod": "vite --mode production", "dev:prod": "vite --mode production",
"build:prod": "vite build", "build:prod": "vite build && npm run pkg",
"build:stage": "vite build --mode staging", "build:stage": "vite build --mode staging",
"pkg":"node make.cjs",
"preview": "vite preview" "preview": "vite preview"
}, },
"repository": { "repository": {

View File

@ -21,13 +21,13 @@ import useSettingsStore from '@/store/modules/settings'
defineProps({ defineProps({
collapse: { collapse: {
type: Boolean, type: Boolean,
required: true required: true,
} },
}) })
const title = import.meta.env.VITE_APP_TITLE; const title = window.yanzhuAppTitle
const settingsStore = useSettingsStore(); const settingsStore = useSettingsStore()
const sideTheme = computed(() => settingsStore.sideTheme); const sideTheme = computed(() => settingsStore.sideTheme)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -2,11 +2,11 @@ export default {
/** /**
* 网页标题 * 网页标题
*/ */
title: import.meta.env.VITE_APP_TITLE, title: window.yanzhuAppTitle,
/** /**
* 侧边栏主题 深色主题theme-dark浅色主题theme-light * 侧边栏主题 深色主题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 * The default is only used in the production env
* If you want to also use it in dev, you can pass ['production', 'development'] * If you want to also use it in dev, you can pass ['production', 'development']
*/ */
errorLog: 'production' errorLog: "production",
} };

View File

@ -1,22 +1,26 @@
<template> <template>
<div class="login main-login"> <div class="login main-login">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form"> <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">数字建安</h3> <h3 class="title">{{title}}</h3>
<el-form-item prop="username" style="margin-top:60px;"> <el-form-item prop="username" style="margin-top:60px;">
<el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="账号"> <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> <template #prefix>
<svg-icon icon-class="user" class="el-input__icon input-icon" />
</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码" <el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="密码" @keyup.enter="handleLogin">
@keyup.enter="handleLogin"> <template #prefix>
<template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> <svg-icon icon-class="password" class="el-input__icon input-icon" />
</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="code" v-if="captchaEnabled"> <el-form-item prop="code" v-if="captchaEnabled">
<el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 63%" <el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter="handleLogin">
@keyup.enter="handleLogin"> <template #prefix>
<template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> <svg-icon icon-class="validCode" class="el-input__icon input-icon" />
</template>
</el-input> </el-input>
<div class="login-code"> <div class="login-code">
<div class="login-code-bg"></div> <div class="login-code-bg"></div>
@ -25,8 +29,7 @@
</el-form-item> </el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;"></el-checkbox> <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;"></el-checkbox>
<el-form-item style="width:100%;"> <el-form-item style="width:100%;">
<el-button :loading="loading" class="btn-login" size="large" type="primary" style="width:100%;" <el-button :loading="loading" class="btn-login" size="large" type="primary" style="width:100%;" @click.prevent="handleLogin">
@click.prevent="handleLogin">
<span v-if="!loading"> </span> <span v-if="!loading"> </span>
<span v-else> ...</span> <span v-else> ...</span>
</el-button> </el-button>
@ -40,100 +43,102 @@
<div class="el-login-footer"> <div class="el-login-footer">
<span>Copyright © 2023-2024 陕西研筑信息科技有限公司 All Rights Reserved.</span> <span>Copyright © 2023-2024 陕西研筑信息科技有限公司 All Rights Reserved.</span>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { getCodeImg } from "@/api/login"; import { getCodeImg } from '@/api/login'
import Cookies from "js-cookie"; import Cookies from 'js-cookie'
import { encrypt, decrypt } from "@/utils/jsencrypt"; import { encrypt, decrypt } from '@/utils/jsencrypt'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
const userStore = useUserStore() const userStore = useUserStore()
const router = useRouter(); const router = useRouter()
const route = useRoute() const route = useRoute()
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance()
let title = ref('系统登录')
title.value = window.yanzhuAppTitle
const loginForm = ref({ const loginForm = ref({
username: "", username: '',
password: "", password: '',
rememberMe: false, rememberMe: false,
code: "", code: '',
uuid: "" uuid: '',
}); })
const loginRules = { const loginRules = {
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }], username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }], password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }],
code: [{ required: true, trigger: "change", message: "请输入验证码" }] code: [{ required: true, trigger: 'change', message: '请输入验证码' }],
}; }
const codeUrl = ref(""); const codeUrl = ref('')
const loading = ref(false); const loading = ref(false)
// //
const captchaEnabled = ref(true); const captchaEnabled = ref(true)
// //
const register = ref(false); const register = ref(false)
const redirect = ref(undefined); const redirect = ref(undefined)
function handleLogin() { function handleLogin() {
proxy.$refs.loginRef.validate(valid => { proxy.$refs.loginRef.validate((valid) => {
if (valid) { if (valid) {
loading.value = true; loading.value = true
// cookie // cookie
if (loginForm.value.rememberMe) { if (loginForm.value.rememberMe) {
Cookies.set("username", loginForm.value.username, { expires: 30 }); Cookies.set('username', loginForm.value.username, { expires: 30 })
Cookies.set("password", encrypt(loginForm.value.password), { expires: 30 }); Cookies.set('password', encrypt(loginForm.value.password), { expires: 30 })
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 }); Cookies.set('rememberMe', loginForm.value.rememberMe, { expires: 30 })
} else { } else {
// //
Cookies.remove("username"); Cookies.remove('username')
Cookies.remove("password"); Cookies.remove('password')
Cookies.remove("rememberMe"); Cookies.remove('rememberMe')
} }
// action // action
userStore.login(loginForm.value).then(() => { userStore
.login(loginForm.value)
.then(() => {
if (route.query?.redirect) { if (route.query?.redirect) {
location.href = route.query.redirect; location.href = route.query.redirect
} else { } else {
router.push({ path: "/" }); router.push({ path: '/' })
} }
})
}).catch(() => { .catch(() => {
loading.value = false; loading.value = false
// //
if (captchaEnabled.value) { if (captchaEnabled.value) {
getCode(); getCode()
} }
}); })
} }
}); })
} }
function getCode() { function getCode() {
getCodeImg().then(res => { getCodeImg().then((res) => {
captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled; captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled
if (captchaEnabled.value) { if (captchaEnabled.value) {
codeUrl.value = "data:image/gif;base64," + res.img; codeUrl.value = 'data:image/gif;base64,' + res.img
loginForm.value.uuid = res.uuid; loginForm.value.uuid = res.uuid
} }
}); })
} }
function getCookie() { function getCookie() {
const username = Cookies.get("username"); const username = Cookies.get('username')
const password = Cookies.get("password"); const password = Cookies.get('password')
const rememberMe = Cookies.get("rememberMe"); const rememberMe = Cookies.get('rememberMe')
loginForm.value = { loginForm.value = {
username: username === undefined ? loginForm.value.username : username, username: username === undefined ? loginForm.value.username : username,
password: password === undefined ? loginForm.value.password : decrypt(password), password: password === undefined ? loginForm.value.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe) rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
}; }
} }
getCode(); getCode()
getCookie(); getCookie()
</script> </script>
<style lang='scss'> <style lang='scss'>
@ -142,7 +147,7 @@ getCookie();
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 100%; height: 100%;
background-image: url("../assets/images/loginbg.jpeg"); background-image: url('../assets/images/loginbg.jpeg');
background-size: cover; background-size: cover;
position: relative; position: relative;
@ -154,7 +159,7 @@ getCookie();
} }
.login-form-bg { .login-form-bg {
background-image: url("../assets/images/loginbg3.png"); background-image: url('../assets/images/loginbg3.png');
position: absolute; position: absolute;
top: 0%; top: 0%;
width: 80%; width: 80%;
@ -167,7 +172,7 @@ getCookie();
.login-form { .login-form {
border-radius: 6px; border-radius: 6px;
background-image: url("../assets/images/loginbg2.png"); background-image: url('../assets/images/loginbg2.png');
background-size: 100% 100%; background-size: 100% 100%;
width: 420px; width: 420px;
padding: 50px; padding: 50px;
@ -182,7 +187,7 @@ getCookie();
.title { .title {
position: relative; position: relative;
top: -68px; top: -90px;
color: #336699; color: #336699;
font-weight: bold; font-weight: bold;
} }
@ -201,7 +206,7 @@ getCookie();
.el-input__prefix-inner { .el-input__prefix-inner {
svg { svg {
fill: #45C4DD; fill: #45c4dd;
} }
} }
} }

View File

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