调整界面和底座风格基本保持一致
This commit is contained in:
		
							
								
								
									
										203
									
								
								examples/App.vue
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								examples/App.vue
									
									
									
									
									
								
							| @@ -5,17 +5,17 @@ | |||||||
|       <el-button type="text" @click="showTools=false">隐藏工具栏</el-button> |       <el-button type="text" @click="showTools=false">隐藏工具栏</el-button> | ||||||
|       <el-button type="text" @click="handleLogin">点此登录</el-button> |       <el-button type="text" @click="handleLogin">点此登录</el-button> | ||||||
|     </div> |     </div> | ||||||
|     <el-row class="main-content" type="flex"> |     <el-row class="fill" type="flex"> | ||||||
|       <el-scrollbar class="menu" v-if="showTools"> |       <slider-nav v-if="showTools"/> | ||||||
|         <el-input size="small" v-model="search" placeholder="应用名称或文件名" clearable @change="recordSearch"/> |       <el-tabs class="layout fill" type="card" :value="currentTab" @tab-click="handleTabClick" | ||||||
|         <el-menu router> |                @tab-remove="handleTabRemove"> | ||||||
|           <el-menu-item v-for="(menu,j) in menus" :key="j" :index="menu.path"> |         <el-tab-pane label="默认页" class="layoutItem"> | ||||||
|             {{ menu.label }} |           <ai-empty>欢迎使用村微产品库</ai-empty> | ||||||
|           </el-menu-item> |         </el-tab-pane> | ||||||
|         </el-menu> |         <el-tab-pane v-for="op in tabs" :key="op.name" :closable="op.name!='工作台'" :name="op.name" :label="op.label" lazy> | ||||||
|       </el-scrollbar> |           <router-view/> | ||||||
|       <router-view v-if="selectedApp"/> |         </el-tab-pane> | ||||||
|       <ai-empty v-else>请选择应用</ai-empty> |       </el-tabs> | ||||||
|     </el-row> |     </el-row> | ||||||
|     <div v-if="dialog" class="sign-box"> |     <div v-if="dialog" class="sign-box"> | ||||||
|       <ai-sign style="margin: auto" :instance="$axios" :action="{login}" |       <ai-sign style="margin: auto" :instance="$axios" :action="{login}" | ||||||
| @@ -27,9 +27,11 @@ | |||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import {mapState} from "vuex"; | import {mapState} from "vuex"; | ||||||
|  | import SliderNav from "./components/sliderNav"; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: 'app', |   name: 'app', | ||||||
|  |   components: {SliderNav}, | ||||||
|   computed: { |   computed: { | ||||||
|     ...mapState(['apps']), |     ...mapState(['apps']), | ||||||
|     serveName() { |     serveName() { | ||||||
| @@ -39,10 +41,6 @@ export default { | |||||||
|       } |       } | ||||||
|       return names[process.env.NODE_ENV] |       return names[process.env.NODE_ENV] | ||||||
|     }, |     }, | ||||||
|     menus() { |  | ||||||
|       let reg = new RegExp(`.*${this.search.replace(/-/g,'')||''}.*`, 'gi') |  | ||||||
|       return (this.apps || []).filter(e => !this.search || reg.test(e.name) || reg.test(e.label)) |  | ||||||
|     }, |  | ||||||
|     selectedApp() { |     selectedApp() { | ||||||
|       return this.$route.matched.length > 0 |       return this.$route.matched.length > 0 | ||||||
|     }, |     }, | ||||||
| @@ -50,14 +48,26 @@ export default { | |||||||
|       let url = '/auth/oauth/token'; |       let url = '/auth/oauth/token'; | ||||||
|       /project\/sass/g.test(location.pathname) && (url += "?corpId=ww596787bb70f08288") |       /project\/sass/g.test(location.pathname) && (url += "?corpId=ww596787bb70f08288") | ||||||
|       return url |       return url | ||||||
|  |     }, | ||||||
|  |     currentTab() { | ||||||
|  |       let {name, query, hash} = this.$route | ||||||
|  |       return [name, query?.id, hash].join("") | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|  |   watch: { | ||||||
|  |     $route: { | ||||||
|  |       immediate: true, | ||||||
|  |       handler(v) { | ||||||
|  |         this.getTabs(v) | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       token: "", |       token: "", | ||||||
|       search: "", |  | ||||||
|       dialog: false, |       dialog: false, | ||||||
|       showTools: true |       showTools: true, | ||||||
|  |       tabs: [] | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
| @@ -86,12 +96,37 @@ export default { | |||||||
|         this.dialog = true |         this.dialog = true | ||||||
|       }) |       }) | ||||||
|     }, |     }, | ||||||
|     recordSearch() { |     handleTabClick(tab) { | ||||||
|       localStorage.setItem("searchApp", this.search) |       let to = {}, selectedTab = this.tabs.find(e => e.name == tab.name) | ||||||
|     } |       if (selectedTab) { | ||||||
|  |         to = {...selectedTab, params: {tabclick: 1}} | ||||||
|  |       } else { | ||||||
|  |         let {name, query, hash} = tab | ||||||
|  |         to = {name, query, hash, params: {tabclick: 1}} | ||||||
|  |       } | ||||||
|  |       this.$router.push({...to}) | ||||||
|  |     }, | ||||||
|  |     handleTabRemove(id = this.currentTab) { | ||||||
|  |       let tabs = JSON.parse(JSON.stringify(this.tabs)), | ||||||
|  |           index = tabs?.findIndex(e => id == e.name) | ||||||
|  |       if (id == this.currentTab) { | ||||||
|  |         let next = tabs?.[index + 1] || tabs?.[index - 1] | ||||||
|  |         this.handleTabClick(next) | ||||||
|  |       } | ||||||
|  |       this.tabs.splice(index, 1) | ||||||
|  |     }, | ||||||
|  |     getTabs() { | ||||||
|  |       let {name, query, hash} = this.$route | ||||||
|  |       let tab = this.tabs.find(e => e.name == this.currentTab) | ||||||
|  |       if (tab) { | ||||||
|  |       } else if (name) { | ||||||
|  |         let menu = this.apps.find(e => e.name == name) | ||||||
|  |         this.tabs.push({name, query, hash, label: menu?.label}) | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
|   created() { |   created() { | ||||||
|     this.search = localStorage.getItem("searchApp") || "" |     this.getTabs() | ||||||
|     this.token = localStorage.getItem("ui-token") |     this.token = localStorage.getItem("ui-token") | ||||||
|     if (this.token) this.getUserInfo() |     if (this.token) this.getUserInfo() | ||||||
|     wx = jWeixin |     wx = jWeixin | ||||||
| @@ -112,35 +147,6 @@ html, body { | |||||||
|   margin: 0; |   margin: 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| .villageFinance-autocomplete { |  | ||||||
|   width: auto !important; |  | ||||||
|  |  | ||||||
|   li { |  | ||||||
|     line-height: normal !important; |  | ||||||
|     padding: 7px !important; |  | ||||||
|     border-bottom: 1px solid #f1f1f1; |  | ||||||
|  |  | ||||||
|     &:hover { |  | ||||||
|       background-color: #f4f4f4 !important; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .name { |  | ||||||
|     text-overflow: ellipsis; |  | ||||||
|     line-height: normal; |  | ||||||
|     overflow: hidden; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .addr { |  | ||||||
|     font-size: 12px; |  | ||||||
|     color: #b4b4b4; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .highlighted .addr { |  | ||||||
|     color: #ddd; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #app { | #app { | ||||||
|   font-family: 'Avenir', Helvetica, Arial, sans-serif; |   font-family: 'Avenir', Helvetica, Arial, sans-serif; | ||||||
|   -webkit-font-smoothing: antialiased; |   -webkit-font-smoothing: antialiased; | ||||||
| @@ -207,18 +213,6 @@ html, body { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   & > .main-content { |  | ||||||
|     width: 100%; |  | ||||||
|     flex: 1; |  | ||||||
|     min-height: 0; |  | ||||||
|     box-sizing: border-box; |  | ||||||
|  |  | ||||||
|     & > *:last-child { |  | ||||||
|       flex: 1; |  | ||||||
|       min-width: 0; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   .sign-box { |   .sign-box { | ||||||
|     z-index: 99; |     z-index: 99; | ||||||
|     margin: -10px; |     margin: -10px; | ||||||
| @@ -229,5 +223,90 @@ html, body { | |||||||
|     height: 100%; |     height: 100%; | ||||||
|     background: rgba(0, 0, 0, 0.2); |     background: rgba(0, 0, 0, 0.2); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .layout { | ||||||
|  |   flex: 1; | ||||||
|  |   min-width: 0; | ||||||
|  |   height: 100%; | ||||||
|  |   background: #F5F6F9; | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |  | ||||||
|  |   & > .el-tabs__header { | ||||||
|  |     margin-bottom: 0; | ||||||
|  |     background: linear-gradient(180deg, #FCFCFC 0%, #E0E2E4 100%); | ||||||
|  |     height: 40px; | ||||||
|  |     display: flex; | ||||||
|  |     align-items: flex-end; | ||||||
|  |     border: none; | ||||||
|  |  | ||||||
|  |     .el-tabs__nav { | ||||||
|  |       border: none; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .el-tabs__item { | ||||||
|  |       padding: 0 8px 0 12px; | ||||||
|  |       text-align: left; | ||||||
|  |       min-width: 130px; | ||||||
|  |       height: 36px; | ||||||
|  |       line-height: 36px; | ||||||
|  |       border: none; | ||||||
|  |       color: #555; | ||||||
|  |       font-size: 12px; | ||||||
|  |  | ||||||
|  |       & + .el-tabs__item { | ||||||
|  |         margin-left: 2px; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .el-icon-close { | ||||||
|  |         float: right; | ||||||
|  |         width: auto; | ||||||
|  |         height: 100%; | ||||||
|  |         line-height: 36px; | ||||||
|  |         background: transparent; | ||||||
|  |         font-size: 16px; | ||||||
|  |         color: #89b; | ||||||
|  |  | ||||||
|  |         &:hover { | ||||||
|  |           color: #000; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       &.is-active { | ||||||
|  |         border: 1px solid #D8DCE3; | ||||||
|  |         border-bottom: none; | ||||||
|  |         border-radius: 4px 4px 0 0; | ||||||
|  |         background: #F5F6F9; | ||||||
|  |         color: #222; | ||||||
|  |  | ||||||
|  |         &:after { | ||||||
|  |           display: none; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       &:after { | ||||||
|  |         position: absolute; | ||||||
|  |         right: 0; | ||||||
|  |         content: " "; | ||||||
|  |         width: 1px; | ||||||
|  |         background: #D8DCE3; | ||||||
|  |         height: 24px; | ||||||
|  |         top: 50%; | ||||||
|  |         transform: translateY(-50%); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .el-tabs__content { | ||||||
|  |     flex: 1; | ||||||
|  |     min-height: 0; | ||||||
|  |  | ||||||
|  |     .el-tab-pane { | ||||||
|  |       height: 100%; | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|   | |||||||
							
								
								
									
										254
									
								
								examples/components/sliderNav.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								examples/components/sliderNav.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,254 @@ | |||||||
|  | <template> | ||||||
|  |   <section class="sliderNav"> | ||||||
|  |     <el-input class="searchApp" size="small" v-model="searchApp" placeholder="搜索应用" clearable | ||||||
|  |               prefix-icon="iconfont iconSearch" @change="recordSearch"/> | ||||||
|  |     <el-scrollbar class="ai-menu"> | ||||||
|  |       <div v-for="(item,i) in navs" :key="i"> | ||||||
|  |         <div class="rootMenu" :class="{isActive:menuPath.includes(item.name)}" | ||||||
|  |              @click.stop="openKidMenu(item)"> | ||||||
|  |           <i class="prep-icon" :class="item.style||'iconfont iconloudongmoxing'"/> | ||||||
|  |           <span class="menuName fill" v-text="item.label"/> | ||||||
|  |           <i v-if="item.children" class="iconfont" :class="arrowIcon(item.showChildren)"/> | ||||||
|  |         </div> | ||||||
|  |         <div class="kidMenu" v-if="item.showChildren" @click.stop> | ||||||
|  |           <div class="kidPane"> | ||||||
|  |             <div class="submenu wrap" flex v-for="menu in item.children" :key="menu.name"> | ||||||
|  |               <b v-text="menu.label" :class="{menuBtn:menu.type==1,current:menuPath.includes(menu.name)}" | ||||||
|  |                  @click="handleSelect(menu)"/> | ||||||
|  |               <div class="menuBtn" v-for="kid in menu.children" :key="kid.name" v-text="kid.label" | ||||||
|  |                    @click="handleSelect(kid)" | ||||||
|  |                    :class="{current:menuPath.includes(kid.name)}"/> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |       <div class="divider"/> | ||||||
|  |     </el-scrollbar> | ||||||
|  |   </section> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import {mapState} from "vuex"; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   name: "sliderNav", | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       searchApp: "", | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   computed: { | ||||||
|  |     ...mapState(['user', 'apps']), | ||||||
|  |     navs() { | ||||||
|  |       let reg = new RegExp(`.*${this.searchApp?.replace(/-/g,'')||''}.*`, 'gi') | ||||||
|  |       return (this.apps || []).filter(e => !this.searchApp || reg?.test(e.name) || reg?.test(e.label)) | ||||||
|  |     }, | ||||||
|  |     isConsoleRoute() { | ||||||
|  |       return this.$route.name == "工作台" | ||||||
|  |     }, | ||||||
|  |     menuPath() { | ||||||
|  |       let paths = [], current = this.apps?.find(e => e.name == this.$route.name) | ||||||
|  |       const findParent = name => { | ||||||
|  |         let menu = this.apps?.find(e => e.name == name) | ||||||
|  |         if (menu) { | ||||||
|  |           paths.push(menu.name) | ||||||
|  |           if (!!menu.parentId) findParent(menu.parentId) | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       if (current) { | ||||||
|  |         findParent(current.name) | ||||||
|  |       } | ||||||
|  |       return paths | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     openKidMenu(parent) { | ||||||
|  |       if (parent.children) { | ||||||
|  |         parent.showChildren = !parent.showChildren | ||||||
|  |       } else { | ||||||
|  |         this.handleSelect(parent) | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     handleSelect(item) { | ||||||
|  |       if (!item.path) return | ||||||
|  |       if (item.name == this.$route.name) { | ||||||
|  |         //避免同一路由跳转的BUG vue-router官方BUG | ||||||
|  |       } else { | ||||||
|  |         let {name, path} = item | ||||||
|  |         if (/\?app=/.test(path)) { | ||||||
|  |           this.goto({name, query: {app: path.replace(/.+\?app=/, '')}}) | ||||||
|  |         } else if (/\?moduleId=/.test(path)) { | ||||||
|  |           this.goto({name, query: {moduleId: path.replace(/.+\?moduleId=/, '')}}) | ||||||
|  |         } else { | ||||||
|  |           this.goto({name}) | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     goto(item) { | ||||||
|  |       this.$router.push(item) | ||||||
|  |     }, | ||||||
|  |     subMenuIcon(flag) { | ||||||
|  |       return flag ? 'iconfont iconArrow_Down' : "iconfont iconArrow_Right" | ||||||
|  |     }, | ||||||
|  |     arrowIcon(v) { | ||||||
|  |       return v ? "iconArrow_Down" : "iconArrow_Right" | ||||||
|  |     }, | ||||||
|  |     recordSearch() { | ||||||
|  |       localStorage.setItem("searchApp", this.searchApp) | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   created() { | ||||||
|  |     this.searchApp = localStorage.getItem("searchApp") || "" | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .sliderNav { | ||||||
|  |   width: 200px; | ||||||
|  |   height: 100%; | ||||||
|  |   transition: width .1s; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   flex-direction: column; | ||||||
|  |   border-right: 1px solid #e5e5e5; | ||||||
|  |   flex-shrink: 0; | ||||||
|  |   box-sizing: border-box; | ||||||
|  |   background: #EFF1F4; | ||||||
|  |   color: #222; | ||||||
|  |   position: relative; | ||||||
|  |  | ||||||
|  |   .kidMenu { | ||||||
|  |     padding: 0 16px; | ||||||
|  |     background: #EFF1F4; | ||||||
|  |  | ||||||
|  |     .rootName { | ||||||
|  |       font-size: 20px; | ||||||
|  |       color: #333; | ||||||
|  |       cursor: default; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .kidPane { | ||||||
|  |       font-size: 13px; | ||||||
|  |  | ||||||
|  |       .submenu { | ||||||
|  |         margin-top: 8px; | ||||||
|  |         width: 100%; | ||||||
|  |         color: #aaa; | ||||||
|  |  | ||||||
|  |         & > b { | ||||||
|  |           width: 100%; | ||||||
|  |           line-height: 28px; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         & > * { | ||||||
|  |           cursor: default; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .menuBtn { | ||||||
|  |         display: block; | ||||||
|  |         width: 50%; | ||||||
|  |         cursor: pointer; | ||||||
|  |         line-height: 32px; | ||||||
|  |         color: #333; | ||||||
|  |         flex-shrink: 0; | ||||||
|  |  | ||||||
|  |         &:hover { | ||||||
|  |           color: #26f; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         &.current { | ||||||
|  |           color: #26f; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .rootMenu { | ||||||
|  |     padding: 0 16px; | ||||||
|  |     display: flex; | ||||||
|  |     align-items: center; | ||||||
|  |     height: 44px; | ||||||
|  |     cursor: pointer; | ||||||
|  |     box-shadow: 0px -1px 0px 0px #D8DCE3 inset, 0px 1px 0px 0px #FFF inset, -1px 0px 0px 0px #E5E5E5 inset; | ||||||
|  |     gap: 8px; | ||||||
|  |     font-size: 13px; | ||||||
|  |  | ||||||
|  |     .iconfont { | ||||||
|  |       color: #89B; | ||||||
|  |       font-size: 20px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     &.isActive { | ||||||
|  |       color: #26f; | ||||||
|  |  | ||||||
|  |       .iconfont { | ||||||
|  |         color: #26f !important; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     &:hover { | ||||||
|  |       color: #26f; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ::v-deep .ai-menu { | ||||||
|  |     padding-left: 0; | ||||||
|  |     flex: 1; | ||||||
|  |     min-height: 0; | ||||||
|  |  | ||||||
|  |     .el-scrollbar__wrap { | ||||||
|  |       overflow-x: auto; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     &::-webkit-scrollbar { | ||||||
|  |       display: none; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ::v-deep .searchApp { | ||||||
|  |     display: flex; | ||||||
|  |     align-items: center; | ||||||
|  |     height: 44px; | ||||||
|  |     padding: 0 16px; | ||||||
|  |     box-shadow: 0px -1px 0px 0px #E5E5E5 inset; | ||||||
|  |  | ||||||
|  |     .el-input__inner { | ||||||
|  |       border: none; | ||||||
|  |       background: inherit; | ||||||
|  |       padding: 0 28px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .el-input__prefix { | ||||||
|  |       left: 16px; | ||||||
|  |  | ||||||
|  |       .iconSearch { | ||||||
|  |         font-size: 20px; | ||||||
|  |         width: fit-content; | ||||||
|  |         color: #89B; | ||||||
|  |         line-height: 44px; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .divider { | ||||||
|  |     color: #aaa; | ||||||
|  |     border-top: 1px solid #ddd; | ||||||
|  |     position: relative; | ||||||
|  |     font-size: 12px; | ||||||
|  |     margin: 16px 16px 32px; | ||||||
|  |  | ||||||
|  |     &:before { | ||||||
|  |       content: "到达底部"; | ||||||
|  |       position: absolute; | ||||||
|  |       top: 50%; | ||||||
|  |       left: 50%; | ||||||
|  |       transform: translate(-50%, -50%); | ||||||
|  |       padding: 0 16px; | ||||||
|  |       background: #EFF1F4; | ||||||
|  |       white-space: nowrap; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @@ -1,13 +1,10 @@ | |||||||
| import store from "../store"; | import store from "../store"; | ||||||
| import {waiting} from "../utils"; | import {waiting} from "../utils"; | ||||||
|  | import appEntry from "../views/apps/appEntry"; | ||||||
|  | import router from "./router"; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   routes: () => store.state.apps.map(e => { |   routes: () => store.state.apps, | ||||||
|     return { |  | ||||||
|       ...e, |  | ||||||
|       component: () => import(`../views/apps/${e.entry}`) |  | ||||||
|     } |  | ||||||
|   }), |  | ||||||
|   init() { |   init() { | ||||||
|     //约束正则式 |     //约束正则式 | ||||||
|     store.commit("cleanApps") |     store.commit("cleanApps") | ||||||
| @@ -22,57 +19,16 @@ export default { | |||||||
|       if (file.default) { |       if (file.default) { | ||||||
|         let {name, label} = file.default, |         let {name, label} = file.default, | ||||||
|             addApp = { |             addApp = { | ||||||
|               name: [path.replace(/\.\/([^\/]+)\/.*/, '$1'), name].join("_"), label: label || name, |               name: path.replace(/\.\/?(vue)?/g, '')?.split("/").join("_"), label: label || name, | ||||||
|               path: path.replace(/\.(\/.+\/App.+)\.vue$/, '/$1'), |               path: path.replace(/\.(\/.+\/App.+)\.vue$/, '$1'), | ||||||
|               entry: 'appEntry', |               component: appEntry, | ||||||
|               module: file.default |               module: file.default | ||||||
|             } |             } | ||||||
|         waiting.setContent(`加载${name}...`) |         waiting.setContent(`加载${name}...`) | ||||||
|  |         router.addRoute(addApp) | ||||||
|         //命名规范入口文件必须以App开头 |         //命名规范入口文件必须以App开头 | ||||||
|         return store.commit("addApp", addApp) |         return store.commit("addApp", addApp) | ||||||
|       } else return 0 |       } else return 0 | ||||||
|     }))).then(() => waiting.close()) |     }))).then(() => waiting.close()) | ||||||
|     // let files = require.context('../../packages', true, /\.(\/.+)\/App[A-Z][^\/]+\.vue$/) |  | ||||||
|     // files.keys().map(path => { |  | ||||||
|     //   if (files(path).default) { |  | ||||||
|     //     let {name, label} = files(path).default, |  | ||||||
|     //         addApp = { |  | ||||||
|     //           name, label: label || name, |  | ||||||
|     //           path: path.replace(/\.(\/.+\/App.+)\.vue$/, '/packages$1'), |  | ||||||
|     //           entry: 'appEntry', |  | ||||||
|     //           module: files(path).default |  | ||||||
|     //         } |  | ||||||
|     //     //命名规范入口文件必须以App开头 |  | ||||||
|     //     store.commit("addApp", addApp) |  | ||||||
|     //   } |  | ||||||
|     // }) |  | ||||||
|     // let cores = require.context('../../core', true, /\.(\/.+)\/App[^\/]+\.vue$/) |  | ||||||
|     // cores.keys().map(path => { |  | ||||||
|     //   if (cores(path).default) { |  | ||||||
|     //     let {name, label} = cores(path).default, |  | ||||||
|     //         addApp = { |  | ||||||
|     //           name, label: label || name, |  | ||||||
|     //           path: path.replace(/\.(\/.+\/App.+)\.vue$/, '/core$1'), |  | ||||||
|     //           entry: 'appEntry', |  | ||||||
|     //           module: cores(path).default |  | ||||||
|     //         } |  | ||||||
|     //     //命名规范入口文件必须以App开头 |  | ||||||
|     //     store.commit("addApp", addApp) |  | ||||||
|     //   } |  | ||||||
|     // }) |  | ||||||
|     // let project = require.context('../../project', true, /\.(\/.+)\/App[^\/]+\.vue$/) |  | ||||||
|     // project.keys().map(path => { |  | ||||||
|     //   if (project(path).default) { |  | ||||||
|     //     let {name, label} = project(path).default, |  | ||||||
|     //         addApp = { |  | ||||||
|     //           name: [path.replace(/\.\/([^\/]+)\/.*/, '$1'), name].join("_"), label: label || name, |  | ||||||
|     //           path: path.replace(/\.(\/.+\/App.+)\.vue$/, '/project$1'), |  | ||||||
|     //           entry: 'appEntry', |  | ||||||
|     //           module: project(path).default |  | ||||||
|     //         } |  | ||||||
|     //     //命名规范入口文件必须以App开头 |  | ||||||
|     //     store.commit("addApp", addApp) |  | ||||||
|     //   } |  | ||||||
|     // }) |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ export default { | |||||||
|   flex: 1; |   flex: 1; | ||||||
|   min-width: 0; |   min-width: 0; | ||||||
|   min-height: 0; |   min-height: 0; | ||||||
|  |   height: 100%; | ||||||
|  |  | ||||||
|   & > * { |   & > * { | ||||||
|     height: 100%; |     height: 100%; | ||||||
|   | |||||||
| @@ -1,169 +0,0 @@ | |||||||
| <template> |  | ||||||
|   <section class="AppInterview"> |  | ||||||
|     <ai-list v-if="!isDetail"> |  | ||||||
|       <template #title> |  | ||||||
|         <ai-title title="调查走访" isShowBottomBorder isShowArea v-model="search.areaId" :instance="instance" |  | ||||||
|                   :hideLevel="hideLevel" @change="page.current=1,getTableData()"/> |  | ||||||
|       </template> |  | ||||||
|       <template #content> |  | ||||||
|         <ai-search-bar> |  | ||||||
|           <template #left> |  | ||||||
|             <ai-search label="创建日期"> |  | ||||||
|               <el-date-picker |  | ||||||
|                   size="small" |  | ||||||
|                   v-model="search.startTime" |  | ||||||
|                   placeholder="开始日期" |  | ||||||
|                   @change="page.current = 1, getTableData()" |  | ||||||
|                   value-format="yyyy-MM-dd"/> |  | ||||||
|               <el-date-picker |  | ||||||
|                   size="small" |  | ||||||
|                   v-model="search.endTime" |  | ||||||
|                   placeholder="结束日期" |  | ||||||
|                   @change="page.current = 1, getTableData()" |  | ||||||
|                   value-format="yyyy-MM-dd"/> |  | ||||||
|             </ai-search> |  | ||||||
|           </template> |  | ||||||
|           <template #right> |  | ||||||
|             <el-input |  | ||||||
|                 suffix-icon="iconfont iconSearch" |  | ||||||
|                 v-model="search.title" |  | ||||||
|                 placeholder="标题" |  | ||||||
|                 clearable |  | ||||||
|                 v-throttle="() => {page.current = 1, getTableData()}" |  | ||||||
|                 @clear="page.current = 1, search.title = '', getTableData()" |  | ||||||
|                 size="small"/> |  | ||||||
|           </template> |  | ||||||
|         </ai-search-bar> |  | ||||||
|         <ai-table |  | ||||||
|             :tableData="tableData" |  | ||||||
|             :colConfigs="colConfigs" |  | ||||||
|             :total="page.total" |  | ||||||
|             :current.sync="page.current" |  | ||||||
|             :size.sync="page.size" |  | ||||||
|             @getList="getTableData"> |  | ||||||
|           <el-table-column label="操作" align="center" slot="options" fixed="right" width="160"> |  | ||||||
|             <template slot-scope="{row}"> |  | ||||||
|               <div class="table-options"> |  | ||||||
|                 <el-button type="text" title="详情" @click="handleShow(row.id)">详情</el-button> |  | ||||||
|                 <el-button type="text" title="删除" @click="handleDelete(row.id)" |  | ||||||
|                            v-if="permissions('app_appinterview_del')">删除 |  | ||||||
|                 </el-button> |  | ||||||
|               </div> |  | ||||||
|             </template> |  | ||||||
|           </el-table-column> |  | ||||||
|         </ai-table> |  | ||||||
|       </template> |  | ||||||
|     </ai-list> |  | ||||||
|     <interview-detail v-else/> |  | ||||||
|   </section> |  | ||||||
| </template> |  | ||||||
|  |  | ||||||
| <script> |  | ||||||
| import InterviewDetail from "./interviewDetail"; |  | ||||||
| import {mapState} from "vuex"; |  | ||||||
|  |  | ||||||
| export default { |  | ||||||
|   name: "AppInterview", |  | ||||||
|   label: "调查走访", |  | ||||||
|   components: {InterviewDetail}, |  | ||||||
|   provide() { |  | ||||||
|     return { |  | ||||||
|       interview: this |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   props: { |  | ||||||
|     instance: Function, |  | ||||||
|     dict: Object, |  | ||||||
|     permissions: Function |  | ||||||
|   }, |  | ||||||
|   computed: { |  | ||||||
|     ...mapState(['user']), |  | ||||||
|     colConfigs() { |  | ||||||
|       return [ |  | ||||||
|         {label: "标题", prop: "title"}, |  | ||||||
|         {label: "时间", prop: "createTime"}, |  | ||||||
|         {label: "所属区域", prop: "areaName"}, |  | ||||||
|         {label: "操作人", prop: "createUserId", openType: 'userName'}, |  | ||||||
|         {slot: "options"} |  | ||||||
|       ] |  | ||||||
|     }, |  | ||||||
|     isDetail() { |  | ||||||
|       return !!this.$route.query.id |  | ||||||
|     }, |  | ||||||
|     hideLevel() { |  | ||||||
|       return this.user.info.areaList?.length - 1 |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   data() { |  | ||||||
|     return { |  | ||||||
|       search: {startTime: null, endTime: null, title: "", areaId: "445203000000"}, |  | ||||||
|       page: {current: 1, size: 10, total: 0}, |  | ||||||
|       tableData: [] |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   created() { |  | ||||||
|     // this.search.areaId = JSON.parse(JSON.stringify(this.user.info.areaId)) |  | ||||||
|     if (this.isDetail) { |  | ||||||
|     } else this.getTableData() |  | ||||||
|   }, |  | ||||||
|   methods: { |  | ||||||
|     getTableData() { |  | ||||||
|       this.instance.post("/app/appinterview/list", null, { |  | ||||||
|         params: {...this.search, ...this.page} |  | ||||||
|       }).then(res => { |  | ||||||
|         if (res?.data) { |  | ||||||
|           this.tableData = res.data.records |  | ||||||
|           this.page.total = res.data.total |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|       }) |  | ||||||
|     }, |  | ||||||
|     handleShow(id) { |  | ||||||
|       if (id) { |  | ||||||
|         this.$router.push({query: {id}}) |  | ||||||
|       } else this.$message.error('该条数据异常,无法打开!') |  | ||||||
|     }, |  | ||||||
|     handleDelete(ids) { |  | ||||||
|       this.$confirm("是否要删除该调查走访?").then(() => { |  | ||||||
|         this.instance.post("/app/appinterview/delete", null, {params: {ids}}).then(res => { |  | ||||||
|           if (res?.code == 0) { |  | ||||||
|             this.$message.success("删除成功!") |  | ||||||
|             this.getTableData() |  | ||||||
|           } |  | ||||||
|         }) |  | ||||||
|       }).catch(() => 0) |  | ||||||
|     }, |  | ||||||
|     back() { |  | ||||||
|       this.$router.push({query: null}) |  | ||||||
|       this.getTableData() |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .AppInterview { |  | ||||||
|   height: 100%; |  | ||||||
|  |  | ||||||
|   ::v-deep .dateRange { |  | ||||||
|     .dateLabel { |  | ||||||
|       height: 32px; |  | ||||||
|       border: 1px solid #D0D4DC; |  | ||||||
|       line-height: 32px; |  | ||||||
|       padding: 0 8px; |  | ||||||
|       background: #F5F5F5; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .el-input__inner { |  | ||||||
|       border-radius: 0; |  | ||||||
|       transform: translateX(-1px); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   ::v-deep .ai-list__content--right-wrapper { |  | ||||||
|     display: flex; |  | ||||||
|     flex-direction: column; |  | ||||||
|     gap: 10px; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
| @@ -1,97 +0,0 @@ | |||||||
| <template> |  | ||||||
|   <section class="interviewDetail"> |  | ||||||
|     <ai-detail> |  | ||||||
|       <template #title> |  | ||||||
|         <ai-title title="调查随访详情" isShowBottomBorder isShowBack @onBackClick="interview.back()"/> |  | ||||||
|       </template> |  | ||||||
|       <template #content> |  | ||||||
|         <ai-card title="基本信息"> |  | ||||||
|           <template #content> |  | ||||||
|             <ai-wrapper |  | ||||||
|                 label-width="56px"> |  | ||||||
|               <ai-info-item label="标题" isLine>{{ detail.title }}</ai-info-item> |  | ||||||
|               <ai-info-item label="内容" isLine>{{ detail.content }}</ai-info-item> |  | ||||||
|               <ai-info-item label="图片" isLine> |  | ||||||
|                 <div class="images"> |  | ||||||
|                   <el-image |  | ||||||
|                       v-for="(op,i) in detail.fileList" |  | ||||||
|                       :key="i" |  | ||||||
|                       :src="op.accessUrl" |  | ||||||
|                       :preview-src-list="detail.fileList.map(e=>e.accessUrl)"> |  | ||||||
|                     <i slot="placeholder" class="el-icon-picture-outline"/> |  | ||||||
|                     <i slot="error" class="el-icon-picture-outline"/> |  | ||||||
|                   </el-image> |  | ||||||
|                 </div> |  | ||||||
|               </ai-info-item> |  | ||||||
|             </ai-wrapper> |  | ||||||
|           </template> |  | ||||||
|         </ai-card> |  | ||||||
|       </template> |  | ||||||
|       <!-- <template #footer> |  | ||||||
|         <el-button @click="interview.back()">取消</el-button> |  | ||||||
|         <el-button type="primary" @click="submitInterview" v-if="interview.permissions('app_appinterview_edit')">保存</el-button> |  | ||||||
|       </template> --> |  | ||||||
|     </ai-detail> |  | ||||||
|   </section> |  | ||||||
| </template> |  | ||||||
|  |  | ||||||
| <script> |  | ||||||
| export default { |  | ||||||
|   name: "interviewDetail", |  | ||||||
|   inject: ['interview'], |  | ||||||
|   data() { |  | ||||||
|     return { |  | ||||||
|       detail: { |  | ||||||
|         fileList: [] |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   created() { |  | ||||||
|     this.getDetail() |  | ||||||
|   }, |  | ||||||
|   methods: { |  | ||||||
|     getDetail() { |  | ||||||
|       let {id} = this.$route.query |  | ||||||
|       this.interview.instance.post("/app/appinterview/queryDetailById", null, {params: {id}}).then(res => { |  | ||||||
|         if (res?.data) { |  | ||||||
|           this.detail = res.data |  | ||||||
|         } |  | ||||||
|       }) |  | ||||||
|     }, |  | ||||||
|     submitInterview() { |  | ||||||
|       this.$refs.interviewForm.validate(v => { |  | ||||||
|         if (v) { |  | ||||||
|           this.interview.instance.post("/app/appinterview/update-web", this.detail).then(res => { |  | ||||||
|             if (res?.code == 0) { |  | ||||||
|               this.$message.success("保存成功!") |  | ||||||
|               this.interview.back() |  | ||||||
|             } |  | ||||||
|           }) |  | ||||||
|         } |  | ||||||
|       }) |  | ||||||
|     }, |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| .interviewDetail { |  | ||||||
|   height: 100%; |  | ||||||
|  |  | ||||||
|   ::v-deep .images { |  | ||||||
|     display: flex; |  | ||||||
|     gap: 16px; |  | ||||||
|     flex-wrap: wrap; |  | ||||||
|  |  | ||||||
|     &:before { |  | ||||||
|       content: none; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .el-image__inner { |  | ||||||
|       width: 82px !important; |  | ||||||
|       height: 82px !important; |  | ||||||
|       margin-right: 16px; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
| @@ -31,6 +31,7 @@ module.exports = { | |||||||
|     .add(path.resolve(__dirname, 'core')) |     .add(path.resolve(__dirname, 'core')) | ||||||
|     .add(path.resolve(__dirname, 'project')) |     .add(path.resolve(__dirname, 'project')) | ||||||
|     .add(path.resolve(__dirname, 'oms')) |     .add(path.resolve(__dirname, 'oms')) | ||||||
|  |     .add(path.resolve(__dirname, 'examples')) | ||||||
|     .add(path.resolve(__dirname, 'node_modules/dvcp-dv-ui')) |     .add(path.resolve(__dirname, 'node_modules/dvcp-dv-ui')) | ||||||
|     .add(path.resolve(__dirname, 'node_modules/dvcp-ui')) |     .add(path.resolve(__dirname, 'node_modules/dvcp-ui')) | ||||||
|     .end() |     .end() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user