持续集成分支
This commit is contained in:
31
src/views/building.vue
Normal file
31
src/views/building.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<section class="building">
|
||||
<div class="title">功能开发中,敬请期待...</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "building"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.building {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
background-image: url("../assets/building.png");
|
||||
background-size: 400px 300px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center, center;
|
||||
|
||||
.title {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
margin-top: 150px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
42
src/views/console.vue
Normal file
42
src/views/console.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<section class="console">
|
||||
<div class="consoleBg" v-text="`欢迎使用${system.fullTitle}`"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "console",
|
||||
label: "工作台",
|
||||
computed: {
|
||||
...mapState(['sys']),
|
||||
system: v => v.sys.info || {}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.console {
|
||||
height: 100%;
|
||||
|
||||
.consoleBg {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-image: url("https://cdn.cunwuyun.cn/dvcp/consoleBg.png");
|
||||
background-size: 600px 362px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center top;
|
||||
padding-top: 402px;
|
||||
font-size: 32px;
|
||||
font-family: MicrosoftYaHei-Bold, MicrosoftYaHei;
|
||||
font-weight: bold;
|
||||
color: #95A1B0;
|
||||
min-width: 600px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
83
src/views/dvIndex.vue
Normal file
83
src/views/dvIndex.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<section class="dvIndex">
|
||||
<ai-dv-wrapper v-model="activeTab" :views="views" :title="title" :theme="theme" v-if="views.length" :background="bgImg" :type="currentStyle" :titleSize="titleSize">
|
||||
<ai-dv-viewer urlPrefix="/app" :instance="instance" :dict="dict" :id="currentView.id"/>
|
||||
</ai-dv-wrapper>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from "vue";
|
||||
import {waiting} from "../utils";
|
||||
|
||||
export default {
|
||||
name: "dvIndex",
|
||||
provide() {
|
||||
return {
|
||||
dv: this
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentView: v => v.views.find(e => e.id == v.activeTab) || v.views?.[0] || {},
|
||||
background: v => JSON.parse(v.currentView.config || null)?.dashboard?.backgroundImage?.[0]?.url || "",
|
||||
bgImg: v => v.theme == 1 ? 'https://cdn.cunwuyun.cn/dvcp/dv/img/dj-bg.png' : v.background,
|
||||
theme() {
|
||||
if (!this.currentView) return '0'
|
||||
if (!this.currentView.config) return '0'
|
||||
const config = JSON.parse(this.currentView.config)
|
||||
if (config.custom) {
|
||||
return '0'
|
||||
}
|
||||
return config.dashboard.theme
|
||||
},
|
||||
currentStyle: v => JSON.parse(v.currentView.config || null)?.dashboard?.style || "black",
|
||||
titleSize: v => JSON.parse(v.currentView.config || "{}").dashboard?.titleSize
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
instance: this.$request,
|
||||
dict: this.$dict,
|
||||
activeTab: 0,
|
||||
views: [],
|
||||
title: "",
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDvOptions() {
|
||||
let {id} = this.$route.query
|
||||
return id ? this.instance.post("/app/appdiylargescreen/queryLargeScreenProjectDetailById", null, {
|
||||
params: {id, status: 1}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
this.title = res.data.name
|
||||
this.views = res.data.lsList?.map(e => ({...e, label: e.title}))
|
||||
}
|
||||
}) : Promise.reject()
|
||||
},
|
||||
loadDvs() {
|
||||
//新App的自动化格式
|
||||
waiting.init({innerHTML: '应用加载中..'})
|
||||
let apps = require.context('../../apps', true, /\.(\/.+)\/App[A-Z][^\/]+D[Vv]\.vue$/, "lazy")
|
||||
return Promise.all(apps.keys().map(path => apps(path).then(file => {
|
||||
if (file.default) {
|
||||
let {name} = file.default
|
||||
waiting.setContent(`加载${name}...`)
|
||||
Vue.component(name, file.default)
|
||||
} else return 0
|
||||
}))).then(() => {
|
||||
waiting.setContent(`正在进入系统...`)
|
||||
setTimeout(() => waiting.close(), 1000)
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadDvs().then(() => this.getDvOptions())
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dvIndex {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
42
src/views/home.vue
Normal file
42
src/views/home.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<section class="home">
|
||||
<header-nav/>
|
||||
<el-row class="fill" type="flex">
|
||||
<slider-nav/>
|
||||
<main-content class="fill"/>
|
||||
</el-row>
|
||||
<ai-copilot v-if="useCopilot" :http="$request"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SliderNav from "../components/sliderNav";
|
||||
import MainContent from "../components/mainContent";
|
||||
import HeaderNav from "../components/headerNav";
|
||||
import configExtra from "../config.json"
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {HeaderNav, MainContent, SliderNav},
|
||||
computed: {
|
||||
useCopilot: () => !!configExtra?.copilot
|
||||
},
|
||||
created() {
|
||||
import("../../apps/actions").then(extra => {
|
||||
const actions = extra?.default || {}
|
||||
this.$store.hotUpdate({actions})
|
||||
Object.keys(actions)?.map(action => this.$store.dispatch(action))
|
||||
}).catch(() => 0)
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.home {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 48px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
55
src/views/mainEntry.vue
Normal file
55
src/views/mainEntry.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<section class="mainEntry fill">
|
||||
<ai-detail list v-if="hasIntro">
|
||||
<template #content>
|
||||
<ai-intro :id="currentApp.guideId" :instance="$request" @start="handleStartUse"/>
|
||||
</template>
|
||||
</ai-detail>
|
||||
<component v-else :is="app" :instance="$request" :dict="$dict" :permissions="$permissions" :menuName="currentApp.name"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import Building from "./building";
|
||||
import Vue from "vue";
|
||||
import {mapGetters, mapMutations, mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "mainEntry",
|
||||
components: {Building},
|
||||
computed: {
|
||||
...mapState(['logs']),
|
||||
...mapGetters(['mods']),
|
||||
currentApp() {
|
||||
const {fullPath, name} = this.$route
|
||||
return this.mods.find(e => !name ? fullPath.indexOf(e.path) > -1 : name == e.route) || Building
|
||||
},
|
||||
app() {
|
||||
const {currentApp} = this
|
||||
return Vue.component(currentApp?.component) ? currentApp.component : Building
|
||||
},
|
||||
hasIntro() {
|
||||
const {app, currentApp, logs} = this
|
||||
return !!currentApp.guideId && !logs?.closeIntro?.includes(app)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['addCloseIntro']),
|
||||
handleStartUse() {
|
||||
this.addCloseIntro(this.app)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.mainEntry {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
& > * {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
172
src/views/sign.vue
Normal file
172
src/views/sign.vue
Normal file
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<section class="sign">
|
||||
<div class="left signLeftBg">
|
||||
<el-row type="flex" align="middle">
|
||||
<img class="AiIcon" v-if="/[\\\/]/.test(logo.icon)" :src="logo.icon" alt=""/>
|
||||
<ai-icon v-else type="logo" :icon="logo.icon"/>
|
||||
<div v-if="logo.text" class="logoText mar-l8" v-text="logo.text"/>
|
||||
</el-row>
|
||||
<div class="signLeftContent">
|
||||
<div class="titlePane">
|
||||
<b v-text="system.name"/>
|
||||
<div v-text="system.title"/>
|
||||
</div>
|
||||
<div class="subTitle" v-for="(t,i) in subTitles" :key="i" v-html="t"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="projectName mar-b48" :title="system.fullTitle">{{ system.fullTitle }}</div>
|
||||
<ai-sign v-if="system.edition=='saas'" @login="login" :instance="instance" visible :tps="['wxwork']" :sassLogin="!isDev"/>
|
||||
<ai-sign v-else isSignIn @login="login" :instance="instance" visible :showScanLogin="system.edition=='standard'||!system.edition"/>
|
||||
<el-row type="flex" align="middle" class="bottomRecord">
|
||||
<div v-if="system.recordDesc" v-text="system.recordDesc"/>
|
||||
<el-link v-if="system.recordNo" v-text="system.recordNo" :href="system.recordURL"/>
|
||||
<div v-if="system.ssl" v-html="system.ssl"/>
|
||||
</el-row>
|
||||
</div>
|
||||
<app-licence :instance="instance" ref="licence"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapMutations, mapState} from 'vuex'
|
||||
import AppLicence from "../components/AppLicence";
|
||||
|
||||
export default {
|
||||
name: "sign",
|
||||
components: {AppLicence},
|
||||
computed: {
|
||||
...mapState(['user', 'sys']),
|
||||
instance: v => v.$request,
|
||||
system: v => v.sys?.info || {},
|
||||
subTitles() {
|
||||
let list = [
|
||||
"构建全域数字大脑,助力政府科学决策",
|
||||
"全域统一应用入口,移动办公高效协同",
|
||||
"直接触达居民微信,政民互动“零距离”"
|
||||
]
|
||||
return (typeof this.system.desc == "object" ? this.system.desc : JSON.parse(this.system.desc || null)) || list
|
||||
},
|
||||
logo: v => !!v.system.loginLogo ? {icon: v.system.loginLogo, text: v.system.loginLogoText} : {icon: v.system.logo, text: v.system.logoText},
|
||||
isDev: () => process.env.NODE_ENV == "development"
|
||||
},
|
||||
created() {
|
||||
if (this.user.token) {
|
||||
this.handleGotoHome()
|
||||
} else {
|
||||
const {code, auth_code} = this.$route.query
|
||||
if (code) {
|
||||
this.toLogin(code)
|
||||
} else if (auth_code) {
|
||||
this.tpLogin(auth_code)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['setToken']),
|
||||
login(data) {
|
||||
if (data.data == '999') {
|
||||
return this.$refs.licence.show()
|
||||
}
|
||||
if (data?.access_token) {
|
||||
this.setToken([data.token_type, data.access_token].join(" "))
|
||||
this.handleGotoHome()
|
||||
}
|
||||
},
|
||||
handleGotoHome() {
|
||||
this.$message.success("登录成功!")
|
||||
if (this.$route.hash == "#dv") {
|
||||
this.$router.push({name: "数据大屏入口", hash: "#dv"})
|
||||
} else {
|
||||
this.$router.push({name: "Home"})
|
||||
}
|
||||
},
|
||||
toLogin(code) {
|
||||
this.instance.post(`/auth/wechatcp-qr/token`, {
|
||||
code: code,
|
||||
type: 'cpuser'
|
||||
}, {
|
||||
auth: {
|
||||
username: 'villcloud',
|
||||
password: "villcloud"
|
||||
},
|
||||
params: {
|
||||
grant_type: 'password',
|
||||
scope: 'server'
|
||||
}
|
||||
}).then(this.login)
|
||||
},
|
||||
tpLogin(code) {
|
||||
this.instance.post("/auth/wechatcp-qr/token", {code}, {
|
||||
auth: {
|
||||
username: 'villcloud',
|
||||
password: "villcloud"
|
||||
},
|
||||
params: {
|
||||
grant_type: 'password',
|
||||
scope: 'server'
|
||||
}
|
||||
}).then(this.login).catch(() => this.$router.push({}))
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.sign {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
|
||||
.AiIcon {
|
||||
font-size: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.logoText {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
:deep(.left ) {
|
||||
width: 480px;
|
||||
flex-shrink: 0;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
padding-left: 64px;
|
||||
padding-top: 40px;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
|
||||
.iconcunwei1 {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.right ) {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background-color: #F6F8FB;
|
||||
background-image: url("../assets/loginRightTop.png"), url("../assets/loginRightBottom.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: calc(100% - 80px) 0, calc(100% - 40px) 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.bottomRecord {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
gap: 16px;
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
|
||||
.el-link {
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user