初始化
This commit is contained in:
		
							
								
								
									
										27
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| .DS_Store | ||||
| node_modules | ||||
| /dist | ||||
|  | ||||
| # local env files | ||||
| .env.local | ||||
| .env.*.local | ||||
|  | ||||
| # Log files | ||||
| npm-debug.log* | ||||
| yarn-debug.log* | ||||
| yarn-error.log* | ||||
|  | ||||
| # Editor directories and files | ||||
| .idea | ||||
| .vscode | ||||
| *.suo | ||||
| *.ntvs* | ||||
| *.njsproj | ||||
| *.sln | ||||
| *.sw? | ||||
| /package-lock.json | ||||
| /lib | ||||
| .prettierrc | ||||
| /oms/dist/ | ||||
| /project/*/index.js | ||||
| /project/*/dist | ||||
							
								
								
									
										13
									
								
								.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.npmignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| # 忽略目录 | ||||
| examples/ | ||||
| packages/ | ||||
| subPackages/ | ||||
| core/ | ||||
| public/ | ||||
| project/ | ||||
| .idea/ | ||||
|  | ||||
| # 忽略指定文件 | ||||
| vue.config.js | ||||
| babel.config.js | ||||
| *.map | ||||
							
								
								
									
										6
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| registry=http://192.168.1.87:4873/ | ||||
| email=aixianling@sinoecare.com | ||||
| always-auth=true | ||||
| _auth="YWRtaW46YWRtaW4xMjM=" | ||||
| package-lock=false | ||||
|  | ||||
							
								
								
									
										11
									
								
								babel.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								babel.config.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| module.exports = { | ||||
|   presets: [ | ||||
|     '@vue/app', | ||||
|   ], | ||||
|   plugins: [ | ||||
|     // 可选链插件, 其他babel插件也是一样的安装方式 | ||||
|     "@babel/plugin-proposal-optional-chaining", | ||||
|     "@babel/plugin-proposal-nullish-coalescing-operator", | ||||
|     "@babel/plugin-proposal-logical-assignment-operators" | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										4
									
								
								core/.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								core/.npmignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| apps/ | ||||
| index.js | ||||
| *.map | ||||
| vcapps.import.js | ||||
							
								
								
									
										247
									
								
								core/apps/AppAccount/AppAccount.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								core/apps/AppAccount/AppAccount.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | ||||
| <template> | ||||
|   <section class="AppAccount"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="账号管理" isShowBottomBorder/> | ||||
|       <template #left> | ||||
|         <ai-address-book-menu :instance="instance" @select="handleSelect"/> | ||||
|       </template> | ||||
|       <template #content> | ||||
|         <ai-title :title="tableTitle"/> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <el-button type="primary" :disabled="!ids.toString()" @click="batchAllot">功能分配</el-button> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input size="small" placeholder="搜索姓名、手机号" v-model="search.name" clearable | ||||
|                       @change="page.current=1,getTableData()"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :total="page.total" :current.sync="page.current" :size.sync="page.size" | ||||
|                   @getList="getTableData" :col-configs="colConfigs" :dict="dict" | ||||
|                   @selection-change="v=>ids=v.filter(e=>e.sysUserId).map(e=>e.sysUserId)"> | ||||
|           <el-table-column slot="name" label="姓名" width="180px"> | ||||
|             <el-row type="flex" align="middle" slot-scope="{row}"> | ||||
|               <el-image class="avatar" :src="row.avatar" :preview-src-list="[row.avatar]"> | ||||
|                 <el-image slot="error" src="https://cdn.cunwuyun.cn/dvcp/h5/defaultAvatar.png" alt=""/> | ||||
|               </el-image> | ||||
|               <div>{{ row.name }}</div> | ||||
|             </el-row> | ||||
|           </el-table-column> | ||||
|           <el-table-column slot="options" align="center" label="操作" fixed="right" width="160px"> | ||||
|             <el-row type="flex" justify="center" align="middle" slot-scope="{row}"> | ||||
|               <el-button v-if="$permissions('admin_sysuser_distribute')&&!!row.sysUserId" | ||||
|                          type="text" @click="appAllot(row)">功能分配 | ||||
|               </el-button> | ||||
|             </el-row> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <!--功能分配--> | ||||
|     <ai-dialog title="功能分配" :visible.sync="dialog" width="800px" @open="initDialogData" @onConfirm="updateAccount"> | ||||
|       <el-form ref="updateAccountForm" :model="dialogForm" :rules="rules" size="small" | ||||
|                label-width="120px"> | ||||
|         <el-form-item required label="角色" prop="roleId"> | ||||
|           <el-select size="small" placeholder="请选择角色" :value="dialogForm.roleId" filterable | ||||
|                      v-model="dialogForm.roleId" clearable> | ||||
|             <el-option v-for="(op,i) in accountRoles" :key="i" :label="op.name" :value="op.id"/> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="行政地区" prop="areaId"> | ||||
|           <ai-area-select v-model="dialogForm.areaId" always-show :instance="instance" | ||||
|                           clearable @fullname="v=>dialogForm.areaFullName=v" | ||||
|                           @name="v=>dialogForm.areaName=v" | ||||
|                           :disabledLevel="disabledLevel"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="党组织" prop="organizationId" v-if="user.info.organizationId"> | ||||
|           <el-cascader :options="partyOrgOps" v-model="dialogForm.organizationId" | ||||
|                        :props="cascaderProps" :show-all-levels="false" clearable/> | ||||
|         </el-form-item> | ||||
|         <!--        <el-form-item label="职务" prop="position">--> | ||||
|         <!--          <el-input placeholder="请输入职务" v-model="dialogForm.position" clearable/>--> | ||||
|         <!--        </el-form-item>--> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
| import AiAddressBookMenu from "../../components/AiAddressBookMenu"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppAccount", | ||||
|   components: {AiAddressBookMenu}, | ||||
|   label: "账号管理(村微sass版)", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     cascaderProps() { | ||||
|       return { | ||||
|         value: 'id', | ||||
|         checkStrictly: true, | ||||
|         emitPath: false | ||||
|       } | ||||
|     }, | ||||
|     partyOrgOps() { | ||||
|       let initData = JSON.parse(JSON.stringify(this.optionsParty)), | ||||
|           ops = initData.filter(e => !e.parentId) | ||||
|       ops.map(e => this.addChild(e, initData)) | ||||
|       return ops | ||||
|     }, | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {type: 'selection', align: 'center'}, | ||||
|         {label: "姓名", slot: "name"}, | ||||
|         {label: "职务", prop: "position", align: 'center', width: "120px"}, | ||||
|         {label: "部门", prop: "departmentNames", align: 'center', width: "120px"}, | ||||
|         {label: "联系方式", prop: "mobile", align: 'center', width: "120px"}, | ||||
|         {label: "账号状态", prop: "status", dict: "wxUserStatus", width: "120px"}, | ||||
|         {label: "账号角色", prop: "roleName", width: "120px", align: '120px'}, | ||||
|         {label: "地区", prop: "areaName", width: "120px"}, | ||||
|         {label: "党组织", prop: "organizationName", align: 'center', width: "120px"}, | ||||
|         {slot: "options"} | ||||
|       ] | ||||
|     }, | ||||
|     tableTitle() { | ||||
|       return this.condition ? this.condition + `(${this.page.total})` : '请选择组织或标签' | ||||
|     }, | ||||
|     rules() { | ||||
|       return { | ||||
|         name: [{required: true, message: "请填写姓名"}], | ||||
|         // organizationId: [{required: true, message: "请选择党组织"}], | ||||
|         // unitId: [{required: true, message: "请选择单位"}], | ||||
|         areaId: [{required: true, message: '请选择地区', trigger: 'change'}], | ||||
|         roleId: [{required: true, message: "请选择角色"}], | ||||
|         phone: [{required: true, message: "请输入手机号码"}] | ||||
|       } | ||||
|     }, | ||||
|     disabledLevel() { | ||||
|       return this.user.info.areaList?.length || 0 | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       condition: "", | ||||
|       accountRoles: [], | ||||
|       page: {current: 1, size: 10, total: 0}, | ||||
|       dialog: false, | ||||
|       dialogForm: {}, | ||||
|       optionsParty: [], | ||||
|       tableData: [], | ||||
|       search: {name: ""}, | ||||
|       ids: [] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getTableData() { | ||||
|       this.instance.post("/app/wxcp/wxuser/list", null, { | ||||
|         params: {...this.page, ...this.search} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data?.records | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleSelect(v) { | ||||
|       if (v.type == 0) { | ||||
|         //选择部门 | ||||
|         let {id: departmentId, name} = v | ||||
|         this.condition = name | ||||
|         this.search = {departmentId} | ||||
|       } else if (v.type == 1) { | ||||
|         //选择标签 | ||||
|         let {id: tagIds, tagname: name} = v | ||||
|         this.condition = name | ||||
|         this.search = {tagIds} | ||||
|       } | ||||
|       this.page.current = 1 | ||||
|       this.getTableData() | ||||
|     }, | ||||
|     initDialogData() { | ||||
|       //用于优化初始化数据 | ||||
|       this.getAccountRoles() | ||||
|       this.searchSysAll() | ||||
|     }, | ||||
|     getAccountRoles() { | ||||
|       this.accountRoles.length == 0 && this.instance.post("/admin/role-acc/list-all").then(res => { | ||||
|         if (res?.data) { | ||||
|           this.accountRoles = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     batchAllot() { | ||||
|       this.dialog = true | ||||
|       this.dialogForm = {areaId: this.user.info.areaId, sysUserIds: this.ids} | ||||
|     }, | ||||
|     appAllot(row) { | ||||
|       this.dialog = true | ||||
|       this.dialogForm = JSON.parse(JSON.stringify({ | ||||
|         ...row, | ||||
|         sysUserIds: [row.sysUserId], | ||||
|         areaId: row.areaId || this.user.info.areaId | ||||
|       })); | ||||
|     }, | ||||
|     // 获取党组织树形 | ||||
|     searchSysAll() { | ||||
|       if (this.user.info.organizationId && this.optionsParty.length == 0) { | ||||
|         this.instance.post('/app/partyOrganization/queryPartyOrganizationServiceList').then((res) => { | ||||
|           if (res?.data) { | ||||
|             res.data = res.data.map(a => { | ||||
|               return {...a, label: a.name} | ||||
|             }); | ||||
|             this.optionsParty = res.data.filter(e => !e.parentId) | ||||
|             this.optionsParty.map(t => this.addChild(t, res.data)); | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|     // 修改 | ||||
|     updateAccount() { | ||||
|       this.$refs.updateAccountForm.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post("/app/wxcp/wxuser/empower", this.dialogForm).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.dialog = false; | ||||
|               this.$message.success("修改成功") | ||||
|               this.getTableData(); | ||||
|             } else { | ||||
|               this.$message.error(res?.msg) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load('wxUserStatus') | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppAccount { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .avatar { | ||||
|     width: 40px; | ||||
|     height: 40px; | ||||
|     margin-right: 10px; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-list__content--left { | ||||
|     margin-right: 2px; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-form { | ||||
|     .el-cascader { | ||||
|       width: 100%; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										156
									
								
								core/apps/AppDictionary/AppDictionary.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								core/apps/AppDictionary/AppDictionary.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | ||||
| <template> | ||||
|   <section class="AppDictionary"> | ||||
|     <ai-list v-if="!showDetail"> | ||||
|       <ai-title slot="title" title="数据字典" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <el-button type="primary" size="small" icon="iconfont iconAdd" @click="addDict" | ||||
|                        v-if="$permissions('admin_sysdictionary_add')">添加 | ||||
|             </el-button> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input size="small" v-model="search.condition" placeholder="数据项" clearable | ||||
|                       @change="page.current=1,getDicts()" prefix-icon="iconfont iconSearch"/> | ||||
|             <el-button type="primary" size="small" icon="iconfont iconSearch" | ||||
|                        @click="page.current=1,getDicts()">查询 | ||||
|             </el-button> | ||||
|             <el-button size="small" icon="el-icon-refresh-right" @click="resetSearch">重置</el-button> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <el-table size="mini" :data="dictList" header-cell-class-name="table-header" tooltip-effect="light" | ||||
|                   row-class-name="table-row" cell-class-name="table-cell" @expand-change="getDictInfo"> | ||||
|           <el-table-column type="expand"> | ||||
|             <el-row slot-scope="{row}" type="flex" align="middle" style="flex-wrap: wrap"> | ||||
|               <el-tag v-for="(op,i) in row.detail||[]" :key="i" style="margin: 4px">{{ op.dictValue }}|{{ op.dictName }} | ||||
|                 {{ op.dictColor ? '| ' + op.dictColor : '' }} | ||||
|               </el-tag> | ||||
|             </el-row> | ||||
|           </el-table-column> | ||||
|           <el-table-column align="center" label="数据项" prop="code"/> | ||||
|           <el-table-column align="center" label="数据项名称" prop="name"/> | ||||
|           <el-table-column align="center" label="操作"> | ||||
|             <div slot-scope="{row}"> | ||||
|               <el-button type="text" @click="openDetail(row.id)" v-text="'编辑'" | ||||
|                          v-if="$permissions('admin_sysdictionary_edit')"/> | ||||
|               <el-button type="text" @click="handleDelete(row.id)" v-text="'删除'" | ||||
|                          v-if="$permissions('admin_sysdictionary_del')"/> | ||||
|             </div> | ||||
|           </el-table-column> | ||||
|           <div slot="empty" class="no-data"></div> | ||||
|         </el-table> | ||||
|         <div class="pagination"> | ||||
|           <el-pagination background :current-page.sync="page.current" :total="page.total" | ||||
|                          layout="total,prev, pager, next,sizes, jumper" | ||||
|                          @size-change="handleSizeChange" | ||||
|                          :page-size="page.size" | ||||
|                          :page-sizes="[10, 20, 50, 100,200]" | ||||
|                          @current-change="getDicts"/> | ||||
|         </div> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <dict-detail v-else :instance="instance" :permissions="permissions"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import DictDetail from "./dictDetail"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppDictionary", | ||||
|   components: {DictDetail}, | ||||
|   label: "数据字典", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     showDetail() { | ||||
|       return this.$route.hash == "#add" | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       page: { | ||||
|         current: 1, | ||||
|         total: 0, | ||||
|         size: 10 | ||||
|       }, | ||||
|       search: { | ||||
|         condition: "" | ||||
|       }, | ||||
|       dictList: [], | ||||
|       id: '' | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     resetSearch() { | ||||
|       this.page.current = 1; | ||||
|       this.search.condition = ''; | ||||
|       this.getDicts(); | ||||
|     }, | ||||
|     getDicts() { | ||||
|       this.instance.post("/admin/dictionary/queryDictList", null, { | ||||
|         params: { | ||||
|           ...this.page, | ||||
|           name: this.search.condition | ||||
|         } | ||||
|       }).then(res => { | ||||
|         this.dictList = res.data.records.map(e => { | ||||
|           return {...e, detail: []} | ||||
|         }) | ||||
|         this.page.total = res.data.total | ||||
|       }) | ||||
|     }, | ||||
|     addDict() { | ||||
|       this.$router.push({hash: "#add"}) | ||||
|     }, | ||||
|     handleDelete(id) { | ||||
|       this.$confirm("确定要删除该数据项吗?", { | ||||
|         type: "error" | ||||
|       }).then(() => { | ||||
|         this.instance.post("/admin/dictionary/deleteDict", null, { | ||||
|           params: {id} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.getDicts(); | ||||
|             this.$message.success("删除成功!") | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     openDetail(id) { | ||||
|       this.$router.push({query: {id}, hash: "#add"}) | ||||
|     }, | ||||
|     handleSizeChange(val) { | ||||
|       this.page.size = val; | ||||
|       this.getDicts(); | ||||
|     }, | ||||
|     getDictInfo(row) { | ||||
|       if (row.detail.length) { | ||||
|         row.detail = [] | ||||
|       } else { | ||||
|         this.getDict(row.id).then(res => { | ||||
|           if (res && res.data) { | ||||
|             row.detail = res.data.dictionaryDetails || [] | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|     getDict(dictionaryId) { | ||||
|       return this.instance.post("/admin/dictionary/queryDictDetail", null, { | ||||
|         params: {dictionaryId} | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     this.getDicts() | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppDictionary { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										202
									
								
								core/apps/AppDictionary/dictDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								core/apps/AppDictionary/dictDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,202 @@ | ||||
| <template> | ||||
|   <section class="dictDetail"> | ||||
|     <ai-detail> | ||||
|       <ai-title slot="title" title="字典信息" isShowBottomBorder isShowBack @onBackClick="$router.push({})"/> | ||||
|       <template #content> | ||||
|         <ai-card title="基本信息"> | ||||
|           <template #content> | ||||
|             <el-form ref="dictDetailForm" :model="form" :rules="rules" size="small" label-width="110px"> | ||||
|               <el-form-item required label="数据项:" prop="code"> | ||||
|                 <el-input v-model="form.code" style="width: 259px;" clearable | ||||
|                           placeholder="请输入..."/> | ||||
|               </el-form-item> | ||||
|               <el-form-item required label="数据项名称:" prop="name"> | ||||
|                 <el-input v-model="form.name" style="width: 259px;" clearable | ||||
|                           placeholder="请输入..."/> | ||||
|               </el-form-item> | ||||
|             </el-form> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <ai-card title="数据值" v-if="$route.query.id"> | ||||
|           <template #right> | ||||
|             <el-button type="text" icon="iconfont iconAdd" | ||||
|                        @click="form.dictionaryDetails.push({name:'',value:'',editable:true})"> 添加 | ||||
|             </el-button> | ||||
|           </template> | ||||
|           <template #content> | ||||
|             <el-table border :data="form.dictionaryDetails" header-cell-class-name="table-header" | ||||
|                       cell-class-name="table-cell"> | ||||
|               <el-table-column align="center" label="值"> | ||||
|                 <div slot-scope="{row}"> | ||||
|                   <el-input size="small" v-if="row.editable" v-model="row.value" clearable/> | ||||
|                   <span v-else>{{ row.dictValue }}</span> | ||||
|                 </div> | ||||
|               </el-table-column> | ||||
|               <el-table-column align="center" label="描述"> | ||||
|                 <div slot-scope="{row}"> | ||||
|                   <el-input size="small" v-if="row.editable" v-model="row.name" clearable/> | ||||
|                   <span v-else>{{ row.dictName }}</span> | ||||
|                 </div> | ||||
|               </el-table-column> | ||||
|               <el-table-column align="center" label="颜色"> | ||||
|                 <div slot-scope="{row}"> | ||||
|                   <el-color-picker v-if="row.editable" v-model="row.dictColor" size="medium"></el-color-picker> | ||||
|                   <span v-else>{{ row.dictColor || '未设置' }}</span> | ||||
|                 </div> | ||||
|               </el-table-column> | ||||
|               <el-table-column align="center" label="操作" width="109px"> | ||||
|                 <div slot-scope="{row,$index}"> | ||||
|                   <section v-if="row.editable"> | ||||
|                     <el-button style="color: #2EA222" type="text" icon="iconfont iconCorrect" | ||||
|                                @click="addDict(row)"/> | ||||
|                     <el-button style="color: #f46" type="text" icon="iconfont iconClean" | ||||
|                                @click="cancelEdit(row,$index)"/> | ||||
|                   </section> | ||||
|                   <section v-else> | ||||
|                     <el-button class="dict-detail-operation" type="text" icon="iconfont iconEdit" | ||||
|                                @click="editDetail(row)"/> | ||||
|                     <el-button class="dict-detail-operation" type="text" icon="iconfont iconDelete" | ||||
|                                @click="delDictValue(row.id)"/> | ||||
|                   </section> | ||||
|  | ||||
|                 </div> | ||||
|               </el-table-column> | ||||
|             </el-table> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </template> | ||||
|       <template #footer> | ||||
|         <el-button @click="$router.push({})">返回</el-button> | ||||
|         <el-button type="primary" @click="modifyDict">保存</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "dictDetail", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     rules() { | ||||
|       return { | ||||
|         code: [ | ||||
|           {required: true, message: "请填写数据项"} | ||||
|         ], | ||||
|         name: [ | ||||
|           {required: true, message: "请填写数据项名称"} | ||||
|         ], | ||||
|         // dictionaryDetails: [ | ||||
|         //   { | ||||
|         //     validator: (r, v, cb) => { | ||||
|         //       if (v.every(item => item.dictName && item.dictValue)) { | ||||
|         //         cb() | ||||
|         //       } | ||||
|         //     } | ||||
|         //   } | ||||
|         // ] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       form: { | ||||
|         code: "", | ||||
|         name: "", | ||||
|         dictionaryDetails: [] | ||||
|       }, | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     if (this.$route.query.id) this.getDict() | ||||
|   }, | ||||
|   methods: { | ||||
|     getDict() { | ||||
|       this.instance.post("/admin/dictionary/queryDictDetail", null, { | ||||
|         params: {dictionaryId: this.$route.query.id} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           res.data.dictionaryDetails = res.data.dictionaryDetails.map(d => { | ||||
|             return { | ||||
|               ...d, | ||||
|               editable: false, | ||||
|               name: "", | ||||
|               value: "" | ||||
|             } | ||||
|           }) | ||||
|           this.form = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     delDictValue(id) { | ||||
|       this.$confirm("是否要删除该字典值", { | ||||
|         type: 'error' | ||||
|       }).then(() => { | ||||
|         this.instance.post("/admin/dictionary/deletevalue", null, { | ||||
|           params: {id} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("删除成功!") | ||||
|             this.getDict() | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     editDetail(row) { | ||||
|       row.editable = true | ||||
|       row.name = row.dictName | ||||
|       row.value = row.dictValue | ||||
|     }, | ||||
|     addDict(row) { | ||||
|       row.dictValue = row.value | ||||
|       row.dictName = row.name | ||||
|       row.dictionaryId = this.form.id | ||||
|       this.instance.post("/admin/dictionary/updateDetail", row).then(res => { | ||||
|         row.editable = false | ||||
|         row = res.data.data | ||||
|         this.$message.success("提交成功!") | ||||
|       }) | ||||
|     }, | ||||
|     cancelEdit(row, index) { | ||||
|       if (row.id) { | ||||
|         row.editable = false | ||||
|       } else { | ||||
|         this.form.dictionaryDetails.splice(index, 1) | ||||
|       } | ||||
|     }, | ||||
|     modifyDict() { | ||||
|       this.$refs.dictDetailForm.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post("/admin/dictionary/updateDict", this.form).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success("提交成功!") | ||||
|               this.$router.push({}) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .dictDetail { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .el-table__row { | ||||
|  | ||||
|     .el-input__inner { | ||||
|       padding: 0 30px; | ||||
|       border: none; | ||||
|       text-align: center; | ||||
|       background: #ddd; | ||||
|       font-size: 14px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										344
									
								
								core/apps/AppQyWxConfig/AppQyWxConfig.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								core/apps/AppQyWxConfig/AppQyWxConfig.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,344 @@ | ||||
| <template> | ||||
|   <section class="AppQyWxConfig"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="企业微信配置" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <el-button type="primary" @click="add" icon="iconfont iconAdd">新增</el-button> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input size="small" placeholder="搜索名称" v-model="search.name" clearable | ||||
|                       @change="page.current=1,getTableData()"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :total="page.total" :current.sync="page.current" :size.sync="page.size" | ||||
|                   @getList="getTableData" :col-configs="colConfigs"> | ||||
|           <el-table-column slot="status" align="center" label="状态" width="150"> | ||||
|             <template v-slot="{ row }"> | ||||
|               <el-switch v-model="row.status" @change="onChange(row)" active-value="1" inactive-value="0" active-color="#5088FF" inactive-color="#D0D4DC"> </el-switch> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|           <el-table-column slot="options" align="center" label="操作" fixed="right" width="200px"> | ||||
|             <el-row type="flex" justify="center" align="middle" slot-scope="{row}"> | ||||
|               <el-button type="text" @click="detail(row)">详情</el-button> | ||||
|               <el-button type="text" @click="del(row)">删除</el-button> | ||||
|             </el-row> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|  | ||||
|     <ai-dialog title="新增" :visible.sync="dialog" width="800px" @onConfirm="confirm"> | ||||
|       <el-form ref="form" :model="dialogForm" :rules="rules" size="small" label-width="180px"> | ||||
|         <el-form-item required label="名称" prop="name"> | ||||
|           <el-input v-model.trim="dialogForm.name" placeholder="请输入名称" show-word-limit maxlength="100"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="企业微信ID" prop="corpId"> | ||||
|           <el-input v-model.trim="dialogForm.corpId" placeholder="请输入企业微信ID" show-word-limit maxlength="32"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="企业微信通讯录SECRET" prop="corpAddressBookSecret"> | ||||
|           <el-input v-model.trim="dialogForm.corpAddressBookSecret" placeholder="请输入企业微信通讯录SECRET" show-word-limit maxlength="64"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="企业微信AESKEY" prop="corpAeskey"> | ||||
|           <el-input v-model.trim="dialogForm.corpAeskey" placeholder="请输入企业微信AESKEY" show-word-limit maxlength="64"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="企业微信AGENTID" prop="corpAgentId"> | ||||
|           <el-input v-model.trim="dialogForm.corpAgentId" placeholder="请输入企业微信AGENTID" show-word-limit maxlength="10"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="企业微信SECRET" prop="corpSecret"> | ||||
|           <el-input v-model.trim="dialogForm.corpSecret" placeholder="请输入企业微信SECRET" show-word-limit maxlength="64"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="企业微信TOKEN" prop="corpToken"> | ||||
|           <el-input v-model.trim="dialogForm.corpToken" placeholder="请输入企业微信TOKEN" show-word-limit maxlength="32"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="小程序APPID" prop="miniappAppid"> | ||||
|           <el-input v-model.trim="dialogForm.miniappAppid" placeholder="请输入小程序APPID" show-word-limit maxlength="32"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="小程序SECRET" prop="miniappSecret"> | ||||
|           <el-input v-model.trim="dialogForm.miniappSecret" placeholder="请输入小程序SECRET" show-word-limit maxlength="32"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="访问域名" prop="dvcpUrl"> | ||||
|           <el-input v-model.trim="dialogForm.dvcpUrl" placeholder="请输入访问域名" show-word-limit maxlength="128"> | ||||
|             <template slot="prepend">Http://</template> | ||||
|           </el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="地区" prop="areaId"> | ||||
|           <ai-area-select :instance="instance" v-model="dialogForm.areaId" alwaysShow  @name="(e)=>dialogForm.areaName=e"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="地图中心点" prop="lat"> | ||||
|           <el-button type="primary" icon="iconfont iconAdd" @click="showMap=true">设置地点</el-button> | ||||
|           <div v-if="dialogForm.lat">{{dialogForm.address}}</div> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="状态" prop="status"> | ||||
|           <el-radio-group v-model.trim="dialogForm.status"> | ||||
|             <el-radio label="1">启用</el-radio> | ||||
|             <el-radio label="0">禁用</el-radio> | ||||
|           </el-radio-group> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|  | ||||
|     <ai-dialog title="地图" :visible.sync="showMap" @opened="initMap" width="800px" class="mapDialog" @onConfirm="selectMap"> | ||||
|       <div id="map"></div> | ||||
|       <el-input id="searchPlaceInput" size="medium" class="searchPlaceInput" clearable v-model="searchPlace" autocomplete="on" | ||||
|                 @change="placeSearch.search(searchPlace)"> | ||||
|         <el-button type="primary" slot="append" @click="placeSearch.search(searchPlace)">搜索</el-button> | ||||
|       </el-input> | ||||
|       <div id="searchPlaceOutput"/> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import {mapState} from "vuex"; | ||||
|   import AMapLoader from "@amap/amap-jsapi-loader" | ||||
|  | ||||
|   export default { | ||||
|     name: "AppQyWxConfig", | ||||
|     label: "企业微信配置", | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|     computed: { | ||||
|       ...mapState(['user']), | ||||
|       colConfigs() { | ||||
|         return [ | ||||
|           {prop: "name", label: "名称",width: 150}, | ||||
|           {prop: "corpId", label: "企业微信ID",width: 180}, | ||||
|           {prop: "corpAddressBookSecret", label: "企业微信通讯录SECRET",width: 200}, | ||||
|           {prop: "corpAgentId", label: "企业微信AGENTID",width: 150}, | ||||
|           {prop: "corpSecret", label: "企业微信SECRET",width: 200}, | ||||
|           {prop: "corpToken", label: "企业微信TOKEN",width: 150}, | ||||
|           {prop: "corpAeskey", label: "企业微信AESKEY",width: 150}, | ||||
|           {prop: "miniappAppid", label: "小程序APPID",width: 150}, | ||||
|           {prop: "miniappSecret", label: "小程序SECRET",width: 150}, | ||||
|           {prop: "lat", label: "纬度",width: 100}, | ||||
|           {prop: "lng", label: "经度",width: 100}, | ||||
|           {prop: "address", label: "中心点",width: 100}, | ||||
|           {slot: "status",}, | ||||
|           {prop: "createTime", label: "创建时间",width: 150}, | ||||
|           {slot: "options"}, | ||||
|         ] | ||||
|       }, | ||||
|       rules() { | ||||
|         return { | ||||
|           name: [{required: true, message: "请填写名称"}], | ||||
|           corpId: [{required: true, message: "请填写企业微信ID"}], | ||||
|           corpAddressBookSecret: [{required: true, message: "请填写企业微信通讯录SECRET"}], | ||||
|           corpAeskey: [{required: true, message: "请填写企业微信AESKEY"}], | ||||
|           corpAgentId: [{required: true, message: "请填写企业微信AGENTID"}], | ||||
|           corpSecret: [{required: true, message: "请填写企业微信SECRET"}], | ||||
|           corpToken: [{required: true, message: "请填写企业微信TOKEN"}], | ||||
|           miniappAppid: [{required: true, message: "请填写小程序APPID"}], | ||||
|           miniappSecret: [{required: true, message: "请填写小程序SECRET"}], | ||||
|           dvcpUrl: [{required: true, message: "请填写访问域名"}], | ||||
|           status: [{required: true, message: "请选择状态",trigger:"change"}], | ||||
|           areaId: [{required: true, message: "请选择地区",trigger:"change"}], | ||||
|           lat: [{required: true, message: "请选择中心点"}], | ||||
|         } | ||||
|       }, | ||||
|     }, | ||||
|     data() { | ||||
|       return { | ||||
|         page: {current: 1, size: 10, total: 0}, | ||||
|         dialog: false, | ||||
|         showMap: false, | ||||
|         map: null, | ||||
|         placeSearch: null, | ||||
|         placeDetail: {}, | ||||
|         searchPlace: "", | ||||
|         dialogForm: {}, | ||||
|         tableData: [], | ||||
|         search: { | ||||
|           name: "" | ||||
|         }, | ||||
|       } | ||||
|     }, | ||||
|     methods: { | ||||
|       selectMap() { | ||||
|         Object.keys(this.placeDetail).map(e=>this.dialogForm[e] = this.placeDetail[e]); | ||||
|         this.showMap = false; | ||||
|       }, | ||||
|       initMap(){ | ||||
|         AMapLoader.load({ | ||||
|           key: '54a02a43d9828a8f9cd4f26fe281e74e', | ||||
|           version: '2.0', | ||||
|           plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete', 'AMap.Geocoder'], | ||||
|         }).then(AMap=>{ | ||||
|           this.map = new AMap.Map('map', { | ||||
|             resizeEnable: true, | ||||
|             zooms: [6, 20], | ||||
|             center: [116.394681, 39.910283], | ||||
|             zoom: 11 | ||||
|           }) | ||||
|           this.placeSearch = new AMap.PlaceSearch({map: this.map}) | ||||
|           new AMap.AutoComplete({ | ||||
|             input: "searchPlaceInput", | ||||
|             output: 'searchPlaceOutput', | ||||
|           }).on('select', e => { | ||||
|             if (e?.poi) { | ||||
|               this.placeSearch.setCity(e.poi.adcode); | ||||
|               this.movePosition(e.poi.location) | ||||
|             } | ||||
|           }) | ||||
|           this.map.on('click', e => { | ||||
|             new AMap.Geocoder().getAddress(e.lnglat, (sta, res) => { | ||||
|               if (res?.regeocode) { | ||||
|                 this.placeDetail = { | ||||
|                   lng: e.lnglat?.lng, | ||||
|                   lat: e.lnglat?.lat, | ||||
|                   address: res.regeocode.formattedAddress | ||||
|                 } | ||||
|               } | ||||
|             }) | ||||
|             this.movePosition(e.lnglat) | ||||
|           }) | ||||
|         }) | ||||
|       }, | ||||
|       movePosition(center) { | ||||
|         if (this.map) { | ||||
|           this.map.clearMap() | ||||
|           this.map.panTo(center) | ||||
|           this.map.add([ | ||||
|             new AMap.Marker({ | ||||
|               position: center, | ||||
|               clickable: true | ||||
|             }) | ||||
|           ]) | ||||
|           this.map.setFitView() | ||||
|         } | ||||
|       }, | ||||
|       onChange(row) { | ||||
|         this.instance.post(`/app/appdvcpconfig/setStatus`,null,{ | ||||
|           params:{ | ||||
|             id:row.id, | ||||
|             status: row.status | ||||
|           } | ||||
|         }).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success(+row.status ? '已启用' : '已禁用'); | ||||
|             this.getTableData(); | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       add() { | ||||
|         this.dialogForm = {}; | ||||
|         this.dialog = true; | ||||
|       }, | ||||
|       del(row){ | ||||
|         this.$confirm("是否要删除?").then(_=>{ | ||||
|           this.instance.post("/app/appdvcpconfig/delete",null,{ | ||||
|             params: { | ||||
|               ids:row.id | ||||
|             } | ||||
|           }).then(res=>{ | ||||
|             if(res.code==0){ | ||||
|               this.$message.success("删除成功"); | ||||
|               this.dialog=false; | ||||
|               this.getTableData(); | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       }, | ||||
|       detail(row){ | ||||
|         this.instance.post("/app/appdvcpconfig/detail",null,{ | ||||
|           params:{ | ||||
|             id:row.id | ||||
|           } | ||||
|         }).then(res=>{ | ||||
|           if(res && res.data) { | ||||
|             this.dialogForm = {...res.data}; | ||||
|             this.dialog = true; | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       getTableData() { | ||||
|         this.instance.post("/app/appdvcpconfig/list", null, { | ||||
|           params: {...this.page, ...this.search} | ||||
|         }).then(res => { | ||||
|           if (res?.data) { | ||||
|             this.tableData = res.data?.records | ||||
|             this.page.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       confirm() { | ||||
|         this.$refs["form"].validate(valid => { | ||||
|           if (valid) { | ||||
|             this.instance.post("/app/appdvcpconfig/addOrUpdate", { | ||||
|               ...this.dialogForm, | ||||
|             }).then(res => { | ||||
|               if (res.code == 0) { | ||||
|                 this.$message.success(this.dialogForm.id ? "修改成功" : "新增成功"); | ||||
|                 this.dialog=false; | ||||
|                 this.getTableData(); | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|     }, | ||||
|     created() { | ||||
|       this.dict.load("integralRuleStatus").then(this.getTableData); | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .AppQyWxConfig { | ||||
|     height: 100%; | ||||
|  | ||||
|  | ||||
|     ::v-deep .mapDialog{ | ||||
|       .el-dialog__body { | ||||
|         padding: 0; | ||||
|  | ||||
|         .ai-dialog__content { | ||||
|           padding: 0; | ||||
|         } | ||||
|  | ||||
|         .ai-dialog__content--wrapper { | ||||
|           padding: 0 !important; | ||||
|           position: relative; | ||||
|         } | ||||
|  | ||||
|         #map { | ||||
|           width: 100%; | ||||
|           height: 500px; | ||||
|         } | ||||
|  | ||||
|         .searchPlaceInput { | ||||
|           position: absolute; | ||||
|           width: 250px; | ||||
|           top: 30px; | ||||
|           left: 25px; | ||||
|         } | ||||
|  | ||||
|         #searchPlaceOutput { | ||||
|           position: absolute; | ||||
|           width: 250px; | ||||
|           left: 25px; | ||||
|           height: initial; | ||||
|           top: 80px; | ||||
|           background: white; | ||||
|           z-index: 250; | ||||
|           max-height: 300px; | ||||
|           overflow-y: auto; | ||||
|  | ||||
|           .auto-item { | ||||
|             text-align: left; | ||||
|             font-size: 14px; | ||||
|             padding: 8px; | ||||
|             box-sizing: border-box; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										443
									
								
								core/apps/AppRightsManager/AppRightsManager.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								core/apps/AppRightsManager/AppRightsManager.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,443 @@ | ||||
| <template> | ||||
|   <section class="AppRightsManager"> | ||||
|     <ai-list v-if="!showDetail"> | ||||
|       <ai-title slot="title" title="权限管理" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <ai-select placeholder="请选择应用" v-model="search.appId" :selectList="appList" | ||||
|                        @change="searchList"/> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input | ||||
|                 size="small" | ||||
|                 v-model="search.roleName" | ||||
|                 placeholder="角色名称" | ||||
|                 clearable | ||||
|                 @change="searchList()" | ||||
|                 suffix-icon="iconfont iconSearch"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <el-button size="small" type="primary" icon="iconfont iconAdd" | ||||
|                        @click="$router.push({hash:'#add'})" | ||||
|                        v-if="$permissions('admin_sysapprole_add')"> | ||||
|               添加 | ||||
|             </el-button> | ||||
|             <el-button | ||||
|                 size="small" | ||||
|                 icon="iconfont iconDelete" | ||||
|                 :disabled="!multipleSelection.length" | ||||
|                 class="del-btn-list" | ||||
|                 @click="deleteApp('all')" | ||||
|                 v-if="$permissions('admin_sysapprole_del')" | ||||
|             >删除 | ||||
|             </el-button> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="adminList" :colConfigs="colConfigs" :total="total" :current.sync="page.pageNum" | ||||
|                   :size.sync="page.pageSize" | ||||
|                   @getList="getTableData" :col-configs="colConfigs" :dict="dict" | ||||
|                   @selection-change="v=>multipleSelection=v"> | ||||
|           <el-table-column label="角色用户" slot="users" align="center"> | ||||
|             <template slot-scope="scope"> | ||||
|               <el-tooltip | ||||
|                   effect="light" | ||||
|                   placement="top" | ||||
|                   :disabled="scope.row.users.length <= 2" | ||||
|                   content="更多角色用户请点击详情按钮"> | ||||
|               <span v-if="scope.row.users.length"> | ||||
|                 {{ | ||||
|                   scope.row.users | ||||
|                   .slice(0, 2) | ||||
|                   .map((e) => e.name + "(" + e.phone + ")") | ||||
|                   .join(";") | ||||
|                 }} | ||||
|                 <span v-if="scope.row.users.length > 2">...</span> | ||||
|               </span> | ||||
|                 <span v-else>-</span> | ||||
|               </el-tooltip> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|           <el-table-column slot="options" label="操作" fixed="right" align="center"> | ||||
|             <template slot-scope="{row}"> | ||||
|               <el-button type="text" @click="beforeCopy(row)" v-if="$permissions('admin_sysapprole_edit')">复制 | ||||
|               </el-button> | ||||
|               <el-button type="text" @click="viewApp(row)" v-if="$permissions('admin_sysapprole_detail')">详情 | ||||
|               </el-button> | ||||
|               <el-button type="text" @click="openRightsGraph(row)" v-if="$permissions('admin_sysapprole_detail')">关系图 | ||||
|               </el-button> | ||||
|               <el-button type="text" @click="toAddAppRole(row)" v-if="$permissions('admin_sysapprole_edit')">编辑 | ||||
|               </el-button> | ||||
|               <el-button type="text" @click="deleteApp(row)" v-if="$permissions('admin_sysapprole_del')">删除</el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|         <ai-dialog | ||||
|             title="应用角色详情" | ||||
|             :visible.sync="viewShow" | ||||
|             width="600px" | ||||
|             customFooter> | ||||
|           <ai-card title="基本信息"> | ||||
|             <template #content> | ||||
|               <ai-wrapper> | ||||
|                 <ai-info-item label="应用角色名称" :value="viewInfo.name"/> | ||||
|                 <ai-info-item label="应用名称" :value="viewInfo.appName"/> | ||||
|               </ai-wrapper> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card title="权限信息"> | ||||
|             <template #content> | ||||
|               <ai-wrapper> | ||||
|                 <ai-info-item :label="viewInfo.appName" isLine> | ||||
|                   {{ roleList.map(e => e.label).join('、') }} | ||||
|                 </ai-info-item> | ||||
|               </ai-wrapper> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card title="角色账号"> | ||||
|             <template #right> | ||||
|             <span style="text-align: right; color: #999" | ||||
|             >共<span | ||||
|                 style="color: #26f" | ||||
|                 v-text="userList.length" | ||||
|             />个账号</span | ||||
|             > | ||||
|             </template> | ||||
|             <template #content> | ||||
|               <div class="datail-table-body" v-if="userList.length"> | ||||
|                 <div class="datail-item" v-for="(item, index) in userList" :key="index"> | ||||
|                   <span class="item-name">{{ item.name }}</span> | ||||
|                   <span style="color: #999">{{ item.phone }}</span> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <template #footer> | ||||
|             <el-button | ||||
|                 type="primary" | ||||
|                 @click="toAddAppRole(viewInfo)" | ||||
|                 v-if="$permissions('admin_sysapprole_edit')" | ||||
|             >编辑角色 | ||||
|             </el-button> | ||||
|           </template> | ||||
|         </ai-dialog> | ||||
|         <ai-dialog title="权限关系图" :visible.sync="rightsGraph" class="rightsGraphDialog" customFooter> | ||||
|           <rights-graph :instance="instance" :dict="dict" :app="selectApp"/> | ||||
|           <el-button slot="footer" @click="rightsGraph=false">关闭</el-button> | ||||
|         </ai-dialog> | ||||
|         <!--复制角色--> | ||||
|         <el-dialog | ||||
|             class="editStyle" | ||||
|             :visible.sync="copyDialog" | ||||
|             width="520px" | ||||
|             @close="dataInit()" | ||||
|             title="复制角色"> | ||||
|           <el-form :model="form" label-width="80px"> | ||||
|             <el-form-item label="角色名" :rules="[{ required: true, message: '', trigger: 'blur' }]"> | ||||
|               <el-input | ||||
|                   v-model="editName" | ||||
|                   placeholder="请输入..." | ||||
|                   size="small" | ||||
|                   clearable | ||||
|               /> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|           <div slot="footer" style="text-align: center"> | ||||
|             <el-button | ||||
|                 style="width: 92px" | ||||
|                 size="small" | ||||
|                 @click="copyDialog = false" | ||||
|             >取消 | ||||
|             </el-button | ||||
|             > | ||||
|             <el-button | ||||
|                 style="width: 92px" | ||||
|                 size="small" | ||||
|                 type="primary" | ||||
|                 @click="copyFn()" | ||||
|                 :disabled="!editName" | ||||
|             > | ||||
|               确认 | ||||
|             </el-button> | ||||
|           </div> | ||||
|         </el-dialog> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <rights-add v-else :instance="instance" :dict="dict" :permissions="permissions"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import RightsAdd from "./rightsAdd"; | ||||
| import RightsGraph from "./rightsGraph"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppRightsManager", | ||||
|   components: {RightsGraph, RightsAdd}, | ||||
|   label: "权限管理", | ||||
|   provide() { | ||||
|     return { | ||||
|       top: this | ||||
|     } | ||||
|   }, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|     actions: { | ||||
|       default: () => ({ | ||||
|         list: '/admin/role-app/page', | ||||
|         apps: '/admin/role-app/list-all', | ||||
|         delete: '/admin/role-app/del', | ||||
|         detail: '/admin/role-app/queryById-checked', | ||||
|         modify: '/admin/role-app/modify', | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {type: "selection"}, | ||||
|         {label: "应用", prop: "appName", width: '120px'}, | ||||
|         {label: "角色名", prop: "name", width: '100px'}, | ||||
|         {label: "用户数量", prop: "roleCount", align: 'center', width: '80px'}, | ||||
|         {slot: "users"}, | ||||
|         {slot: "options"} | ||||
|       ] | ||||
|     }, | ||||
|     showDetail() { | ||||
|       return this.$route.hash == "#add" | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       page: {pageNum: 1, pageSize: 10}, | ||||
|       search: {appId: '', roleName: ''}, | ||||
|       adminList: [], //列表数据 | ||||
|       total: 0, | ||||
|       appList: [], //下拉选择列表 | ||||
|       multipleSelection: [], | ||||
|       delShow: false, | ||||
|       delParams: "", | ||||
|       delIds: [], | ||||
|       viewShow: false, | ||||
|       viewInfo: {}, | ||||
|       roleList: [], //详情权限列表 | ||||
|       row: {}, | ||||
|       copyDialog: false, | ||||
|       titleDel: "", | ||||
|       form: {}, | ||||
|       editName: "", | ||||
|       userList: [], | ||||
|       rightsGraph: false, | ||||
|       selectApp: {} | ||||
|     }; | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTableData(); | ||||
|     this.getAppList(); | ||||
|   }, | ||||
|   methods: { | ||||
|     //查询table列表 | ||||
|     getTableData() { | ||||
|       this.adminList = []; | ||||
|       this.instance.post(this.actions.list, null, { | ||||
|         params: {...this.page, ...this.search} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.total = res.data.total; | ||||
|           this.adminList = res.data.records; | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     //查询下拉列表 | ||||
|     getAppList() { | ||||
|       this.instance.post(this.actions.apps).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.appList = res.data?.map(e => ({dictName: e.name, dictValue: e.id})) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     //查询 | ||||
|     searchList() { | ||||
|       this.page.pageNum = 1; | ||||
|       this.getTableData(); | ||||
|     }, | ||||
|     //添加按钮 | ||||
|     toAddAppRole(item) { | ||||
|       this.$router.push({ | ||||
|         hash: "#add", | ||||
|         query: { | ||||
|           id: item.id, | ||||
|           name: item.name, | ||||
|           appId: item.appId, | ||||
|         }, | ||||
|       }); | ||||
|     }, | ||||
|     //删除 | ||||
|     deleteApp(e) { | ||||
|       if (e == "all") { | ||||
|         this.multipleSelection.map((item) => { | ||||
|           this.delIds.push(item.id); | ||||
|         }); | ||||
|         this.delParams = `ids=${this.delIds}`; | ||||
|         this.titleDel = "确定要执行删除操作吗?"; | ||||
|       } else { | ||||
|         this.delParams = `ids=${e.id}`; | ||||
|         this.titleDel = "确定需要删除该角色吗?"; | ||||
|       } | ||||
|       this.$confirm(this.titleDel, { | ||||
|         type: "error", | ||||
|       }).then(() => { | ||||
|         this.instance.post(`${this.actions.delete}?${this.delParams}`).then(res => { | ||||
|           if (res?.msg == "success") { | ||||
|             this.getTableData(); | ||||
|           } else { | ||||
|             this.$message.error(res.msg); | ||||
|           } | ||||
|         }); | ||||
|       }).catch(() => 0); | ||||
|     }, | ||||
|     //查看信息 | ||||
|     viewApp(e) { | ||||
|       this.userList = e.users; | ||||
|       this.viewInfo = e; | ||||
|       this.viewShow = true; | ||||
|       this.getRowInfo(this.viewInfo.appId, this.viewInfo.id); | ||||
|     }, | ||||
|     //查询 row 信息 | ||||
|     getRowInfo(appId, id) { | ||||
|       this.roleList = []; | ||||
|       this.instance.post(`${this.actions.detail}?id=${appId}&roleId=${id}`) | ||||
|       .then(res => { | ||||
|         if (res?.data) { | ||||
|           this.roleList = res.data.list.filter(e => e.checked) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     //复制 | ||||
|     beforeCopy(row) { | ||||
|       this.row = row; | ||||
|       this.copyDialog = true; | ||||
|       this.getRowInfo(this.row.appId, this.row.id); | ||||
|     }, | ||||
|     //确认复制 | ||||
|     copyFn() { | ||||
|       let crr = []; | ||||
|       let appRoleList = this.roleList; | ||||
|       for (let i = 0; i < appRoleList.length; i++) { | ||||
|         if (appRoleList[i].checked) { | ||||
|           crr.push(appRoleList[i].id); | ||||
|           if (appRoleList[i].list.length) { | ||||
|             for (let j = 0; j < appRoleList[i].list.length; j++) { | ||||
|               if (appRoleList[i].list[j].checked) { | ||||
|                 crr.push(appRoleList[i].list[j].id); | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       this.instance.post(`${this.actions.modify}?menus=${crr}`, null, { | ||||
|         params: { | ||||
|           roleName: this.editName, | ||||
|           appId: this.row.appId, | ||||
|         }, | ||||
|       }) | ||||
|       .then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.$message({message: "复制成功", type: "success"}); | ||||
|           this.copyDialog = false; | ||||
|           this.searchList() | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     dataInit() { | ||||
|       this.multipleSelection = []; | ||||
|       this.row = {}; | ||||
|     }, | ||||
|     handleSelectionChange(val) { | ||||
|       this.multipleSelection = val; | ||||
|     }, | ||||
|     openRightsGraph(row) { | ||||
|       this.rightsGraph = true | ||||
|       this.selectApp = row | ||||
|     } | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppRightsManager { | ||||
|   height: 100%; | ||||
|  | ||||
|  | ||||
|   ::v-deep .ai-dialog { | ||||
|     .ai-card { | ||||
|       box-shadow: none; | ||||
|       border: 1px solid #eee; | ||||
|  | ||||
|       .aibar { | ||||
|         height: 40px; | ||||
|         background: #f3f6f9; | ||||
|       } | ||||
|  | ||||
|       .ai-card__body { | ||||
|         padding: 0 16px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .rightsGraphDialog { | ||||
|     .el-dialog__body { | ||||
|       padding: 0; | ||||
|     } | ||||
|  | ||||
|     .ai-dialog__content { | ||||
|       padding-bottom: 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .datail-table-body { | ||||
|     width: 100%; | ||||
|     height: auto; | ||||
|     margin-bottom: 16px; | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|  | ||||
|     .datail-item { | ||||
|       flex-shrink: 0; | ||||
|       width: 50%; | ||||
|       height: 24px; | ||||
|       line-height: 24px; | ||||
|  | ||||
|       span { | ||||
|         display: inline-block; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|  | ||||
|       .item-name { | ||||
|         width: 102px; | ||||
|         padding-left: 16px; | ||||
|         color: #333; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .datail-item:nth-of-type(2n - 1) { | ||||
|       border-right: 1px solid rgba(208, 212, 220, 1); | ||||
|       width: calc(50% - 1px); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .padd-l0 { | ||||
|     padding-left: 0 !important; | ||||
|   } | ||||
|  | ||||
|   .pad-l16 { | ||||
|     padding-left: 16px; | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										195
									
								
								core/apps/AppRightsManager/rightsAdd.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								core/apps/AppRightsManager/rightsAdd.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,195 @@ | ||||
| <template> | ||||
|   <ai-detail class="rightsAdd"> | ||||
|     <ai-title :title="addTitle" slot="title" isShowBottomBorder isShowBack @onBackClick="back"/> | ||||
|     <template #content> | ||||
|       <el-form size="small" ref="rightsForm" :model="form" label-width="120px" :rules="rules"> | ||||
|         <ai-card title="基本信息"> | ||||
|           <template #content> | ||||
|             <el-form-item label="应用角色名称" prop="roleName"> | ||||
|               <el-input v-model="form.roleName" placeholder="请输入应用角色名称" clearable/> | ||||
|             </el-form-item> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <ai-card title="权限信息"> | ||||
|           <template #content> | ||||
|             <el-form-item label="应用" prop="appId"> | ||||
|               <ai-select placeholder="请选择应用" v-model="form.appId" :selectList="top.appList" | ||||
|                          @change="getPermissions"/> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="权限列表" prop="menus" v-if="form.appId"> | ||||
|               <div class="roleList"> | ||||
|                 <el-input v-model="filterText" placeholder="请输入..." clearable suffix-icon="iconfont iconSearch" | ||||
|                           @change="$refs.tree.filter(filterText)" :validate-event="false"/> | ||||
|                 <div class="tree_list"> | ||||
|                   <el-tree class="filter-tree" ref="roleTree" | ||||
|                            :data="roleList" | ||||
|                            show-checkbox | ||||
|                            :props="defaultProps" | ||||
|                            default-expand-all | ||||
|                            :check-strictly="false" | ||||
|                            node-key="id" | ||||
|                            :default-checked-keys="form.menus" | ||||
|                            :filter-node-method="filterNode" | ||||
|                            @check="handleMenusSelect"/> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </el-form-item> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </el-form> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button @click="back()">取消</el-button> | ||||
|       <el-button type="primary" @click="confirm">保存</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
| <script> | ||||
|  | ||||
| export default { | ||||
|   name: "rightsAdd", | ||||
|   inject: ['top'], | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       form: {}, | ||||
|       roleName: '', | ||||
|       id: '', | ||||
|       appList: [], | ||||
|       roleList: [], | ||||
|       defaultProps: { | ||||
|         children: 'list', | ||||
|         label: 'name' | ||||
|       }, | ||||
|       treeList: [], | ||||
|       filterText: '', | ||||
|       msgTitle: '添加', | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     if (this.isEdit) { | ||||
|       let {id, appId, name: roleName} = this.$route.query | ||||
|       this.form = {appId, menus: [], id, roleName} | ||||
|       this.getPermissions() | ||||
|       this.msgTitle = '编辑' | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     isEdit() { | ||||
|       return this.$route.query.id | ||||
|     }, | ||||
|     addTitle() { | ||||
|       return this.isEdit ? '编辑应用角色' : '新增应用角色' | ||||
|     }, | ||||
|     rules() { | ||||
|       return { | ||||
|         roleName: {required: true, message: '请输入应用角色名称'}, | ||||
|         appId: {required: true, message: '请选择应用'}, | ||||
|         menus: {required: true, message: '请选择权限列表内容'}, | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     filterNode(value, data) { | ||||
|       if (!value) return true; | ||||
|       return data.name.indexOf(value) !== -1; | ||||
|     }, | ||||
|     //应用名称选择 获取权限列表 | ||||
|     getId(data) { | ||||
|       if (data.list.length) { | ||||
|         data.list.forEach(item => { | ||||
|           this.getId(item) | ||||
|         }) | ||||
|       } else { | ||||
|         if (data.checked) { | ||||
|           this.form.menus?.push(data.id) | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     getPermissions() { | ||||
|       this.filterText = '' | ||||
|       let {appId: id, id: roleId} = this.form | ||||
|       this.instance.post(this.top.actions.detail, null, { | ||||
|         params: {id, roleId} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.roleList = [res.data]; | ||||
|           if (this.isEdit) { | ||||
|             this.roleList.forEach(e => this.getId(e)) | ||||
|           } | ||||
|           this.roleList = this.roleList.filter(item => !(item.component && item.isApp == 0 && item.isMenu == 0)) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleMenusSelect(node, selected) { | ||||
|       this.$set(this.form, 'menus', [...selected?.checkedKeys]) | ||||
|       this.$refs.rightsForm.validateField('menus') | ||||
|     }, | ||||
|     //保存提交 | ||||
|     confirm() { | ||||
|       this.$refs.rightsForm.validate(v => { | ||||
|         if (v) { | ||||
|           let menus = [this.$refs.roleTree?.getHalfCheckedKeys(), this.$refs.roleTree?.getCheckedKeys()]?.flat()?.toString() | ||||
|           this.instance.post(this.top.actions.modify, null, { | ||||
|             params: {...this.form, menus} | ||||
|           }).then(res => { | ||||
|             if (res?.msg == "success") { | ||||
|               this.$message.success(`${this.msgTitle}应用角色成功`) | ||||
|               this.back() | ||||
|               this.top.searchList() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     //取消 返回 | ||||
|     back() { | ||||
|       this.$router.push({}) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| .rightsAdd { | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   position: relative; | ||||
|  | ||||
|   .el-form-item { | ||||
|     .el-select { | ||||
|       width: 100%; | ||||
|     } | ||||
|  | ||||
|     &.is-error { | ||||
|       .roleList { | ||||
|         border-color: #f46; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .roleList { | ||||
|     background-color: #fcfcfc; | ||||
|     border-radius: 2px; | ||||
|     border: solid 1px #d0d4dc; | ||||
|     padding: 8px; | ||||
|  | ||||
|     .input { | ||||
|       display: flex; | ||||
|       justify-content: space-between; | ||||
|       padding: 5px; | ||||
|       margin: 0; | ||||
|     } | ||||
|  | ||||
|     .tree_list { | ||||
|       padding: 5px; | ||||
|       height: 370px; | ||||
|       overflow: auto; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										192
									
								
								core/apps/AppRightsManager/rightsGraph.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								core/apps/AppRightsManager/rightsGraph.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | ||||
| <template> | ||||
|   <section class="rightsGraph"> | ||||
|     <div id="RightGraph"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import * as echarts from "echarts"; | ||||
|  | ||||
| export default { | ||||
|   name: "rightsGraph", | ||||
|   inject: ['top'], | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     app: Object | ||||
|   }, | ||||
|   computed: { | ||||
|     graphData() { | ||||
|       let data = [...this.users, ...this.nodes].map(e => { | ||||
|         if (e.x) { | ||||
|           return e | ||||
|         } else return {...e, ...this.renderPosition(e)} | ||||
|       }) | ||||
|       return [ | ||||
|         { | ||||
|           data, | ||||
|           links: this.links, | ||||
|           categories: data.map(e => e.category).flat().map(name => ({name})) | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       graph: null, | ||||
|       nodes: [], | ||||
|       links: [], | ||||
|       users: [] | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     graphData: { | ||||
|       deep: true, handler() { | ||||
|         this.refreshGraph() | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     initGraph() { | ||||
|       let dom = document.querySelector("#RightGraph") | ||||
|       if (dom) { | ||||
|         this.graph = echarts.init(dom) | ||||
|         this.graph.setOption({ | ||||
|           tooltip: {}, | ||||
|           series: [ | ||||
|             { | ||||
|               type: 'graph', | ||||
|               layout: 'none', | ||||
|               roam: true, | ||||
|               label: { | ||||
|                 show: true, | ||||
|                 position: 'right', | ||||
|                 formatter: '{b}' | ||||
|               }, | ||||
|               labelLayout: { | ||||
|                 hideOverlap: true, | ||||
|               }, | ||||
|               scaleLimit: { | ||||
|                 min: 0.4, | ||||
|                 max: 4 | ||||
|               }, | ||||
|               lineStyle: { | ||||
|                 color: 'target', | ||||
|                 curveness: 0.1 | ||||
|               }, | ||||
|               emphasis: { | ||||
|                 focus: 'adjacency', | ||||
|                 lineStyle: { | ||||
|                   width: 5 | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           ] | ||||
|         }) | ||||
|         this.graph.on('click', this.handleNodeClick) | ||||
|       } | ||||
|     }, | ||||
|     refreshGraph() { | ||||
|       this.graph?.setOption({ | ||||
|         series: this.graphData | ||||
|       }) | ||||
|     }, | ||||
|     getAppRoles(role) { | ||||
|       if (role) { | ||||
|         this.nodes.push({...role, category: '应用角色', value: "应用角色", symbolSize: 15}) | ||||
|       } else this.instance.post(this.top.actions.list, null, { | ||||
|         params: {pageSize: 999} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           res.data.records.map(e => { | ||||
|             this.getUsers(e.users, e.id) | ||||
|             this.nodes.push({...e, category: '应用角色', value: "应用角色"}) | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getUsers(pending, source) { | ||||
|       pending?.map(e => { | ||||
|         if (!this.users.some(u => u.id == e.phone)) { | ||||
|           this.users.push({id: e.phone, name: e.name, symbolSize: 5, category: '用户', value: "用户"}) | ||||
|         } | ||||
|         this.links.push({source, target: e.phone}) | ||||
|       }) | ||||
|     }, | ||||
|     getPermissions({appId: id, id: roleId, name: category, dataIndex}) { | ||||
|       const addNodes = (list, source, category, pos) => { | ||||
|         list?.map(e => { | ||||
|           let node = { | ||||
|             ...e, | ||||
|             symbolSize: 5, | ||||
|             category, | ||||
|             value: e.list?.length > 0 ? "应用" : "权限", | ||||
|           } | ||||
|           node = {...node, ...this.renderPosition(pos || node)} | ||||
|           this.nodes.splice(dataIndex, 0, node) | ||||
|           this.links.push({source, target: e.id}) | ||||
|           addNodes(e.list, e.id, e.label, node) | ||||
|         }) | ||||
|       } | ||||
|       id && this.instance.post(this.top.actions.detail, null, { | ||||
|         params: {id, roleId} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           addNodes(res.data.list, roleId, category) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleNodeClick(v) { | ||||
|       let {data: role, dataIndex} = v | ||||
|       if (!this.nodes.some(e => e.category == role?.name)) { | ||||
|         role && this.getPermissions({...role, dataIndex}) | ||||
|       } | ||||
|     }, | ||||
|     renderPosition(node) { | ||||
|       node = JSON.parse(JSON.stringify(node)) | ||||
|       let pos = {x: 0, y: 0} | ||||
|       if (node?.x) { | ||||
|         pos.x = Math.max(this.graph?.getWidth() / 3 * 2, node.x) + 100 + Math.random() * 50 | ||||
|         pos.y = node.y + Math.random() * 100 - 50 | ||||
|       } else if (node.value == '应用角色') { | ||||
|         pos.x = this.graph?.getWidth() / 3 - 200 + Math.random() * 200 | ||||
|         pos.y = this.graph?.getHeight() / 2 - 100 + Math.random() * 200 | ||||
|       } else if (node.value == '应用') { | ||||
|         pos.x = this.graph?.getWidth() / 3 * 2 - 100 + Math.random() * 100 | ||||
|         pos.y = Math.random() * this.graph?.getHeight() | ||||
|       } else if (node.value == '用户') { | ||||
|         pos.x = Math.random() * 50 | ||||
|         pos.y = Math.random() * this.graph?.getHeight() | ||||
|       } else { | ||||
|         pos.x = this.graph?.getWidth() - 100 + Math.random() * 100 | ||||
|         pos.y = Math.random() * this.graph?.getHeight() | ||||
|       } | ||||
|       return pos | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getAppRoles(this.app) | ||||
|     if (this.app?.id) { | ||||
|       this.getUsers(this.app.users, this.app.id) | ||||
|       this.getPermissions(this.app) | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.$nextTick(() => { | ||||
|       this.initGraph() | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .rightsGraph { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep #RightGraph { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     min-height: 500px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										211
									
								
								core/apps/AppSystemAccount/AppSystemAccount.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								core/apps/AppSystemAccount/AppSystemAccount.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,211 @@ | ||||
| <template> | ||||
|   <section class="AppSystemAccount"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="账号管理" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <el-button type="primary" icon="iconfont iconAdd" @click="dialog=true">添加</el-button> | ||||
| <!--            <el-button type="primary" :disabled="!ids.toString()" @click="batchAllot">功能分配</el-button>--> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input size="small" placeholder="搜索姓名、手机号" v-model="search.condition" clearable | ||||
|                       @change="page.pageNum=1,getTableData()"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :total="page.total" :current.sync="page.pageNum" :size.sync="page.pageSize" | ||||
|                   @getList="getTableData" :col-configs="colConfigs" :dict="dict" | ||||
|                   @selection-change="v=>ids=v.map(e=>e.id)"> | ||||
|           <el-table-column slot="name" label="姓名" width="180px"> | ||||
|             <el-row type="flex" align="middle" slot-scope="{row}"> | ||||
|               <el-image class="avatar" :src="row.avatar" :preview-src-list="[row.avatar]"> | ||||
|                 <el-image slot="error" src="https://cdn.cunwuyun.cn/dvcp/h5/defaultAvatar.png" alt=""/> | ||||
|               </el-image> | ||||
|               <div>{{ row.name }}</div> | ||||
|             </el-row> | ||||
|           </el-table-column> | ||||
|           <el-table-column slot="options" align="center" label="操作" fixed="right" width="160px"> | ||||
|             <el-row type="flex" justify="center" align="middle" slot-scope="{row}"> | ||||
|               <el-button type="text" @click="appAllot(row)">功能分配</el-button> | ||||
|               <el-button type="text" @click="handleDelete(row.id)">删除</el-button> | ||||
|             </el-row> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <!--添加账号、功能分配--> | ||||
|     <ai-dialog :title="dialogTitle" :visible.sync="dialog" width="600px" @open="initDialogData" | ||||
|                @onConfirm="updateAccount" @closed="dialogForm={}"> | ||||
|       <el-form ref="updateAccountForm" :model="dialogForm" :rules="rules" size="small" | ||||
|                label-width="120px"> | ||||
|         <el-form-item required label="姓名" prop="name"> | ||||
|           <el-input v-model.trim="dialogForm.name" placeholder="请输入..." clearable | ||||
|                     :maxLength="15"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item required label="手机号码" prop="phone"> | ||||
|           <el-input v-model.trim="dialogForm.phone" placeholder="请输入..." clearable | ||||
|                     :maxLength="11" :disabled="isEdit"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item required label="角色" prop="roleId"> | ||||
|           <el-select size="small" placeholder="请选择角色" :value="dialogForm.roleId" filterable | ||||
|                      v-model="dialogForm.roleId" clearable> | ||||
|             <el-option v-for="(op,i) in accountRoles" :key="i" :label="op.name" :value="op.id"/> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="行政地区" prop="areaId"> | ||||
|           <ai-area-get v-model="dialogForm.areaId" :instance="instance" @select="handleAreaSelect"/> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppSystemAccount", | ||||
|   label: "账号管理", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     cascaderProps() { | ||||
|       return { | ||||
|         value: 'id', | ||||
|         checkStrictly: true, | ||||
|         emitPath: false | ||||
|       } | ||||
|     }, | ||||
|     isEdit() { | ||||
|       return !!this.dialogForm.id | ||||
|     }, | ||||
|     dialogTitle() { | ||||
|       return this.isEdit ? '功能分配' : '添加账号' | ||||
|     }, | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         // {type: 'selection', align: 'center'}, | ||||
|         {label: "姓名", slot: "name"}, | ||||
|         {label: "联系方式", prop: "phone", align: 'center'}, | ||||
|         {label: "角色", prop: "roleName", align: 'center'}, | ||||
|         {label: "地区", prop: "areaName"}, | ||||
|         {slot: "options"} | ||||
|       ] | ||||
|     }, | ||||
|     rules() { | ||||
|       return { | ||||
|         name: [{required: true, message: "请填写姓名"}], | ||||
|         // organizationId: [{required: true, message: "请选择党组织"}], | ||||
|         // unitId: [{required: true, message: "请选择单位"}], | ||||
|         // areaId: [{required: true, message: '请选择地区', trigger: 'change'}], | ||||
|         roleId: [{required: true, message: "请选择角色"}], | ||||
|         phone: [{required: true, message: "请输入手机号码"}] | ||||
|       } | ||||
|     }, | ||||
|     disabledLevel() { | ||||
|       return this.user.info.areaList?.length || 0 | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       accountRoles: [], | ||||
|       page: {pageNum: 1, pageSize: 10, total: 0}, | ||||
|       dialog: false, | ||||
|       dialogForm: {}, | ||||
|       tableData: [], | ||||
|       search: {condition: ""}, | ||||
|       ids: [] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getTableData() { | ||||
|       this.instance.post("/admin/user/page", null, { | ||||
|         params: {...this.page, ...this.search} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data?.records | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     initDialogData() { | ||||
|       //用于优化初始化数据 | ||||
|       this.getAccountRoles() | ||||
|     }, | ||||
|     getAccountRoles() { | ||||
|       this.accountRoles.length == 0 && this.instance.post("/admin/role/list-all").then(res => { | ||||
|         if (res?.data) { | ||||
|           this.accountRoles = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     batchAllot() { | ||||
|       this.dialog = true | ||||
|       this.dialogForm = {areaId: this.user.info.areaId, ids: this.ids} | ||||
|     }, | ||||
|     appAllot(row) { | ||||
|       this.dialog = true | ||||
|       this.dialogForm = JSON.parse(JSON.stringify({ | ||||
|         ...row, | ||||
|         areaId: row.areaId || this.user.info.areaId | ||||
|       })); | ||||
|     }, | ||||
|     // 修改 | ||||
|     updateAccount() { | ||||
|       this.$refs.updateAccountForm.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post("/admin/user/addOrEdit", this.dialogForm).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.dialog = false; | ||||
|               this.$message.success("提交成功") | ||||
|               this.getTableData(); | ||||
|             } else { | ||||
|               this.$message.error(res?.msg) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleDelete(ids) { | ||||
|       this.$confirm("是否要删除该账号?").then(() => { | ||||
|         this.instance.post("/admin/user/del", null, { | ||||
|           params: {ids} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.getTableData(); | ||||
|             this.$message.success("删除成功!"); | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     handleAreaSelect(v) { | ||||
|       this.dialogForm.areaName = v?.[0]?.label | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTableData() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppSystemAccount { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .avatar { | ||||
|     width: 40px; | ||||
|     height: 40px; | ||||
|     margin-right: 10px; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-form { | ||||
|     .el-cascader, .el-select { | ||||
|       width: 100%; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										197
									
								
								core/apps/AppUserInfo/AppUserInfo.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								core/apps/AppUserInfo/AppUserInfo.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | ||||
| <template> | ||||
|   <section class="AppUserInfo"> | ||||
|     <ai-detail> | ||||
|       <ai-title slot="title" title="个人中心" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-card title="个人资料"> | ||||
|           <template #right> | ||||
|             <span style="color:#999" v-text="'(如需修改基本信息,请联系管理员)'"/> | ||||
|           </template> | ||||
|           <template #content> | ||||
|             <el-row type="flex" justify="space-between"> | ||||
|               <ai-wrapper> | ||||
|                 <ai-info-item label="姓名"> | ||||
|                   <ai-open-data type="userName" :openid="user.info.name" /> | ||||
|                 </ai-info-item> | ||||
|                 <ai-info-item label="手机号码" :value="user.info.phone"/> | ||||
|                 <ai-info-item label="角色" :value="user.info.roleName"/> | ||||
|                 <ai-info-item label="部门"> | ||||
|                   <ai-open-data type="departmentName" :openid="user.info.departName" /> | ||||
|                 </ai-info-item> | ||||
|                 <ai-info-item label="职位" :value="user.info.position"/> | ||||
|               </ai-wrapper> | ||||
|               <ai-avatar :value="user.info.avatar" :editable="false"/> | ||||
|             </el-row> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <ai-card title="数据权限"> | ||||
|           <template #right> | ||||
|             <span style="color:#999" v-text="'(如需修改基本信息,请联系管理员)'"/> | ||||
|           </template> | ||||
|           <template #content> | ||||
|             <ai-wrapper> | ||||
|               <ai-info-item label="所属地区" :value="user.info.areaList.join('')" isLine/> | ||||
|               <ai-info-item label="所属党组织" :value="user.info.organizationName" isLine/> | ||||
|             </ai-wrapper> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <ai-card title="密码设置"> | ||||
|           <template #right> | ||||
|             <el-button type="text" @click="submitForm">保存</el-button> | ||||
|           </template> | ||||
|           <template #content> | ||||
|             <el-form :model="form" ref="ruleForm" :rules="rules" label-width="100px" size="small"> | ||||
|               <el-form-item label="绑定手机:" prop="phone"> | ||||
|                 <el-row type="flex" align="middle"> | ||||
|                   <span>{{ user.info.phone }}</span> | ||||
|                   <el-button type="primary" style="margin-left: 8px" @click="getCode(user.info.phone,true)" | ||||
|                              :disabled="codeBtn">获取验证码 | ||||
|                     <span v-if="num>0&&codeBtn" style="color:red;">({{ num }}s)</span> | ||||
|                   </el-button> | ||||
|                 </el-row> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="验证码:" prop="code"> | ||||
|                 <el-input v-model.trim="form.code" clearable placeholder="请输入短信验证码"/> | ||||
|                 <el-input style="position: fixed; bottom: -9999px"></el-input> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="新密码:" prop="pass"> | ||||
|                 <el-input type="password" auto-complete="new-password" v-model.trim="form.pass" clearable | ||||
|                           placeholder="8-16位,需要包含字母和数字及特殊字符(~!@#$%^&*,.?_-)" | ||||
|                           show-password/> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="确认密码:" prop="checkPass"> | ||||
|                 <el-input type="password" auto-complete="new-password" placeholder="再次输入密码" | ||||
|                           v-model.trim="form.checkPass" clearable | ||||
|                           show-password/> | ||||
|               </el-form-item> | ||||
|             </el-form> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapMutations, mapState} from "vuex"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppUserInfo", | ||||
|   label: "个人中心", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     rules() { | ||||
|       const validatePass = (rule, value, callback) => { | ||||
|         const reg = /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*,.?_-])[\da-zA-Z~!@#$%^&*,.?_-]{8,16}$/; | ||||
|         if (!reg.test(value)) { | ||||
|           callback(new Error('数字和字母及特殊字符(~!@#$%^&*,.?_-)组合,长度8到16位')); | ||||
|         } else { | ||||
|           if (this.form.checkPass !== '') { | ||||
|             this.$refs.ruleForm.validateField('checkPass'); | ||||
|           } | ||||
|           callback(); | ||||
|         } | ||||
|       } | ||||
|       return { | ||||
|         currentPass: [ | ||||
|           {required: true, message: '请填写当前密码', trigger: 'blur'} | ||||
|         ], | ||||
|         code: [ | ||||
|           {required: true, message: '请填写验证码', trigger: 'blur'} | ||||
|         ], | ||||
|         pass: [ | ||||
|           {validator: validatePass, trigger: 'blur', required: true} | ||||
|         ], | ||||
|         checkPass: [ | ||||
|           { | ||||
|             validator: (r, v, cb) => v ? v != this.form.pass ? cb('两次输入密码不一致') : cb() : cb('请再次输入密码'), | ||||
|             trigger: 'blur', | ||||
|             required: true | ||||
|           } | ||||
|         ], | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       form: {}, | ||||
|       timer: null, | ||||
|       codeBtn: false, | ||||
|       num: 60, | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapMutations(['SignOut']), | ||||
|     getCode(phone, flag) { | ||||
|       const TEL_REGEXP = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/; | ||||
|       if (TEL_REGEXP.test(phone)) { | ||||
|         this.instance.post(`/admin/user/checkPhone`, null, { | ||||
|           params: {phone, flag} | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success("请查看手机短信!"); | ||||
|             this.timer = setInterval(() => { | ||||
|               if (this.num > 0) { | ||||
|                 this.codeBtn = true; | ||||
|                 this.num--; | ||||
|               } else if (this.num == 0) { | ||||
|                 this.codeBtn = false; | ||||
|                 this.num = 60; | ||||
|                 clearInterval(this.timer); | ||||
|  | ||||
|               } | ||||
|             }, 1000) | ||||
|  | ||||
|           } else { | ||||
|             this.$message.error("验证码发送失败!"); | ||||
|           } | ||||
|  | ||||
|         }) | ||||
|  | ||||
|  | ||||
|       } else { | ||||
|         this.$message.error("手机号格式错误!"); | ||||
|       } | ||||
|  | ||||
|     }, | ||||
|     submitForm() { | ||||
|       this.$refs.ruleForm.validate(v => { | ||||
|         if (v) { | ||||
|           let {pass: newPwd, code} = this.form | ||||
|           this.instance.post(`/admin/user/update-pwd`, null, { | ||||
|             params: { | ||||
|               phone: this.user.info.phone, | ||||
|               newPwd, code | ||||
|             } | ||||
|           }).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$confirm("村微提醒您,更换密码成功!", { | ||||
|                 showCancelButton: false | ||||
|               }).then(() => this.SignOut()).catch(() => 0) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppUserInfo { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .ai-list__content--wrapper { | ||||
|     flex-direction: column; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-input__inner { | ||||
|  | ||||
|     -webkit-text-security: disc !important; | ||||
|  | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										242
									
								
								core/components/AiAddressBookMenu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								core/components/AiAddressBookMenu.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,242 @@ | ||||
| <template> | ||||
|   <section class="AiAddressBookMenu"> | ||||
|     <div class="tabsPane"> | ||||
|       <h2 v-for="tab in tabs" :key="tab.name" :class="{tabActive:current==tab.name}" | ||||
|           @click="handleTabClick(tab)">{{ tab.label }}</h2> | ||||
|     </div> | ||||
|     <div class="contentPane"> | ||||
|       <el-input :placeholder="`请输入${currentTab.label}名称`" | ||||
|                 size="small" v-model="search" suffix-icon="iconfont iconSearch" | ||||
|                 @change="handleSearchChange"/> | ||||
|       <div v-if="isTagType" class="addressBook-left__tags"> | ||||
|         <div @click="selected=item" v-for="(item, index) in tags" :key="index" | ||||
|              class="addressBook-left__tags--item" | ||||
|              :class="{'addressBook-left__tags--item-active':selected.id == item.id}"> | ||||
|           <span>{{ item.tagname }}</span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="AiAddressBookMenu-wrapper" v-else> | ||||
|         <div class="AiAddressBookMenu-tree"> | ||||
|           <el-tree | ||||
|             ref="tree" | ||||
|             node-key="id" | ||||
|             :filter-node-method="handleTreeFilter" | ||||
|             :props="defaultProps" :data="list" | ||||
|             :default-expanded-keys="treeRoot" | ||||
|             @current-change="v=>selected=v"> | ||||
|             <div class="tree-container" slot-scope="{ data }"> | ||||
|               <span>{{ data.name }}</span> | ||||
|             </div> | ||||
|           </el-tree> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| /** | ||||
|  * 通讯录选择器 | ||||
|  */ | ||||
| export default { | ||||
|   name: "AiAddressBookMenu", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|   }, | ||||
|   computed: { | ||||
|     tabs() { | ||||
|       return [ | ||||
|         {label: "组织架构", name: 0}, | ||||
|         {label: "标签", name: 1} | ||||
|       ] | ||||
|     }, | ||||
|     currentTab() { | ||||
|       return this.tabs.find(e => e.name == this.current) || {} | ||||
|     }, | ||||
|     isTagType() { | ||||
|       return this.current == 1 | ||||
|     }, | ||||
|     defaultProps() { | ||||
|       return { | ||||
|         children: 'children', | ||||
|         label: 'name' | ||||
|       } | ||||
|     }, | ||||
|     tags() { | ||||
|       return this.list?.filter(e => !this.search || e.tagname?.indexOf(this.search) > -1) | ||||
|     }, | ||||
|     treeRoot() { | ||||
|       let root = this.list?.[0] | ||||
|       return root ? [root?.id] : [] | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       current: 0, | ||||
|       search: "", | ||||
|       list: [], | ||||
|       origin: [], | ||||
|       selected: {} | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     selected(v) { | ||||
|       v && this.$emit('select', {...v, type: this.current}) | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     handleTabClick(tab) { | ||||
|       this.current = tab.name | ||||
|       this.isTagType ? this.getTags() : this.getUnits() | ||||
|       this.$emit('tabClick') | ||||
|     }, | ||||
|     handleTreeFilter(v, data) { | ||||
|       return data?.name?.indexOf(v) > -1 | ||||
|     }, | ||||
|     handleSearchChange(v) { | ||||
|       if (this.isTagType) { | ||||
|       } else { | ||||
|         this.$refs.tree?.filter(v) | ||||
|       } | ||||
|     }, | ||||
|     handleTagClick(tag) { | ||||
|       this.$emit('tag', tag) | ||||
|       this.selected = tag | ||||
|     }, | ||||
|     getUnits() { | ||||
|       this.instance.post(`/app/wxcp/wxdepartment/listAll`).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.list = res.data?.filter(e => !e.parentid) | ||||
|           this.list.map(p => this.addChild(p, res.data, {parent: 'parentid'})) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getTags() { | ||||
|       this.instance.post(`/app/wxcp/wxtag/listAll`).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.origin = JSON.parse(JSON.stringify(res.data)) | ||||
|           this.list = res?.data | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getUnits() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AiAddressBookMenu { | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   background: #FAFAFB; | ||||
|   .tabsPane { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     width: 100%; | ||||
|     height: 40px; | ||||
|     background: #ffffff; | ||||
|  | ||||
|     h2 { | ||||
|       flex: 1; | ||||
|       height: 100%; | ||||
|       line-height: 40px; | ||||
|       color: #222; | ||||
|       font-size: 14px; | ||||
|       text-align: center; | ||||
|       cursor: pointer; | ||||
|       border-bottom: 2px solid transparent; | ||||
|  | ||||
|       &.tabActive { | ||||
|         color: #2266FF; | ||||
|         border-bottom: 2px solid #2266FF; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .AiAddressBookMenu-wrapper { | ||||
|     height: calc(100% - 32px); | ||||
|     .AiAddressBookMenu-tree { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|       overflow: auto; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .contentPane { | ||||
|     height: calc(100% - 56px); | ||||
|     margin: 8px; | ||||
|     overflow: auto; | ||||
|  | ||||
|     .addressBook-left__tags--item { | ||||
|       cursor: pointer; | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
|       height: 40px; | ||||
|       padding: 0 8px 0 16px; | ||||
|       color: #222222; | ||||
|  | ||||
|       &.addressBook-left__tags--item-active, &:hover { | ||||
|         background: #E8EFFF; | ||||
|         color: #2266FF; | ||||
|  | ||||
|         i, span { | ||||
|           color: #2266FF; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       span { | ||||
|         font-size: 14px; | ||||
|       } | ||||
|  | ||||
|       i { | ||||
|         cursor: pointer; | ||||
|         color: #8e9ebf; | ||||
|         font-size: 16px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     span { | ||||
|       color: #222; | ||||
|       font-size: 14px; | ||||
|     } | ||||
|  | ||||
|     ::v-deep .el-tree { | ||||
|       width: 100%; | ||||
|       margin-top: 4px; | ||||
|       background: transparent; | ||||
|       width: fit-content; | ||||
|       min-width: 100%; | ||||
|  | ||||
|       .el-tree-node__content { | ||||
|         display: inline-flex; | ||||
|         min-width: 100%; | ||||
|         height: 32px; | ||||
|  | ||||
|         &:hover { | ||||
|           background: #E8EFFF; | ||||
|           color: #222222; | ||||
|           border-radius: 2px; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|  | ||||
|       .is-current > .el-tree-node__content { | ||||
|         background: #2266FF; | ||||
|  | ||||
|         &:hover { | ||||
|           background: #2266FF; | ||||
|           color: #fff; | ||||
|         } | ||||
|  | ||||
|         span { | ||||
|           color: #fff; | ||||
|           font-weight: bold; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										45
									
								
								core/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								core/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /** | ||||
|  * 系统业务模块 | ||||
|  * @param Vue 外部接入Vue | ||||
|  * @param params showList:打印加载的应用;apps:加载的应用文件名数组 | ||||
|  */ | ||||
|  | ||||
| const install = function (Vue, params) { | ||||
|   if (install.installed) return Promise.resolve() | ||||
|   else { | ||||
|     // 遍历工作控件内的应用 | ||||
|     let apps = [] | ||||
|     let contexts = require.context('.', true, /\.(\/.+)\/App[^\/]+\.vue$/) | ||||
|     if (contexts) { | ||||
|       contexts.keys().map(e => { | ||||
|         if (contexts(e).default) { | ||||
|           if (params?.apps) { | ||||
|             if (params?.apps.includes(contexts(e).default.name)) { | ||||
|               apps.push(contexts(e).default) | ||||
|               Vue.component(contexts(e).default.name, contexts(e).default) | ||||
|             } | ||||
|           } else { | ||||
|             apps.push(contexts(e).default) | ||||
|             Vue.component(contexts(e).default.name, contexts(e).default) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|       // apps.map(e=>{ | ||||
|       //   console.log(e.name,e.label) | ||||
|       // }) | ||||
|       !!params?.showList && console.log(apps.map(e => e.name)) | ||||
|     } | ||||
|     return Promise.resolve(apps) | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| // 判断是否是直接引入文件 | ||||
| if (typeof window !== 'undefined' && window.Vue) { | ||||
|   install(window.Vue) | ||||
| } | ||||
|  | ||||
| export default { | ||||
|   // 导出的对象必须具有 install,才能被 Vue.use() 方法安装 | ||||
|   install | ||||
| } | ||||
							
								
								
									
										9
									
								
								core/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								core/package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| { | ||||
|   "name": "cw-core-webapps", | ||||
|   "description": "系统业务模块", | ||||
|   "version": "1.0.13", | ||||
|   "main": "dist/cw-core-webapps.common.js", | ||||
|   "publishConfig": { | ||||
|     "registry": "http://192.168.1.87:4873/" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										226
									
								
								examples/App.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								examples/App.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,226 @@ | ||||
| <template> | ||||
|   <div id="app"> | ||||
|     <div class="header" v-if="showTools"> | ||||
|       <b v-text="serveName"/> | ||||
|       <el-button type="text" @click="showTools=false">隐藏工具栏</el-button> | ||||
|       <el-button type="text" @click="handleLogin">点此登录</el-button> | ||||
|     </div> | ||||
|     <el-row class="main-content" type="flex"> | ||||
|       <el-scrollbar class="menu" v-if="showTools"> | ||||
|         <el-input size="small" v-model="search" placeholder="应用名称或文件名" clearable @change="recordSearch"/> | ||||
|         <el-menu router> | ||||
|           <el-menu-item v-for="(menu,j) in menus" :key="j" :index="menu.path"> | ||||
|             {{ menu.label }} | ||||
|           </el-menu-item> | ||||
|         </el-menu> | ||||
|       </el-scrollbar> | ||||
|       <router-view v-if="selectedApp"/> | ||||
|       <ai-empty v-else>请选择应用</ai-empty> | ||||
|     </el-row> | ||||
|     <div v-if="dialog" class="sign-box"> | ||||
|       <ai-sign style="margin: auto" :instance="$axios" :action="{login:'/auth/oauth/token?corpId=ww596787bb70f08288'}" | ||||
|                visible @login="getToken" :showScanLogin="false"/> | ||||
|     </div> | ||||
|     <el-button type="info" v-if="!showTools" class="fixedBtn" @click="showTools=true">显示工具栏</el-button> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
|  | ||||
| export default { | ||||
|   name: 'app', | ||||
|   computed: { | ||||
|     ...mapState(['apps']), | ||||
|     serveName() { | ||||
|       let names = { | ||||
|         development: "村微产品库", | ||||
|         oms: "运营平台产品分库", | ||||
|       } | ||||
|       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() { | ||||
|       return this.$route.matched.length > 0 | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       token: "", | ||||
|       search: "", | ||||
|       dialog: false, | ||||
|       showTools: true | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     setToken() { | ||||
|       localStorage.setItem('ui-token', this.token) | ||||
|       this.$message.success("设置token成功!") | ||||
|     }, | ||||
|     getToken(params) { | ||||
|       this.token = params.access_token | ||||
|       this.setToken() | ||||
|       this.dialog = false | ||||
|       location.reload() | ||||
|     }, | ||||
|     getUserInfo() { | ||||
|       this.$axios.post("/admin/user/detail-phone").then(res => { | ||||
|         if (res && res.data) { | ||||
|           this.$store.commit("setUserInfo", res.data) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleLogin() { | ||||
|       this.$axios.delete("/auth/token/logout").then(() => { | ||||
|         this.dialog = true | ||||
|       }) | ||||
|     }, | ||||
|     recordSearch() { | ||||
|       localStorage.setItem("searchApp", this.search) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.search = localStorage.getItem("searchApp") || "" | ||||
|     this.token = localStorage.getItem("ui-token") | ||||
|     if (this.token) this.getUserInfo() | ||||
|     wx = jWeixin | ||||
|   }, | ||||
|   destroyed() { | ||||
|     this.token = "" | ||||
|   }, | ||||
|   mounted() { | ||||
|     document.title = this.serveName | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| html, body { | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   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 { | ||||
|   font-family: 'Avenir', Helvetica, Arial, sans-serif; | ||||
|   -webkit-font-smoothing: antialiased; | ||||
|   -moz-osx-font-smoothing: grayscale; | ||||
|   color: #2c3e50; | ||||
|   overflow: hidden; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   gap: 5px; | ||||
|  | ||||
|   .fixedBtn { | ||||
|     position: fixed; | ||||
|     top: 0; | ||||
|     right: 60px; | ||||
|     opacity: 0; | ||||
|  | ||||
|     &:hover { | ||||
|       opacity: 1; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   li { | ||||
|     list-style-type: none; | ||||
|   } | ||||
|  | ||||
|   .menu { | ||||
|     min-width: 200px; | ||||
|     flex-shrink: 0; | ||||
|     height: 100%; | ||||
|     border-right: solid 1px #e6e6e6; | ||||
|     background-color: #fff; | ||||
|  | ||||
|     .el-scrollbar__view { | ||||
|       padding: 4px 8px; | ||||
|       display: flex; | ||||
|       flex-direction: column; | ||||
|     } | ||||
|  | ||||
|     .el-menu { | ||||
|       border: none; | ||||
|       flex: 1; | ||||
|       min-height: 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   & > .header { | ||||
|     text-align: start; | ||||
|     box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | ||||
|     height: 60px; | ||||
|     flex-shrink: 0; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     padding: 0 16px; | ||||
|  | ||||
|     & > b { | ||||
|       flex: 1; | ||||
|       min-width: 0; | ||||
|     } | ||||
|  | ||||
|     .el-input { | ||||
|       max-width: 25%; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   & > .main-content { | ||||
|     width: 100%; | ||||
|     flex: 1; | ||||
|     min-height: 0; | ||||
|     box-sizing: border-box; | ||||
|  | ||||
|     & > *:last-child { | ||||
|       flex: 1; | ||||
|       min-width: 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .sign-box { | ||||
|     z-index: 99; | ||||
|     margin: -10px; | ||||
|     display: flex; | ||||
|     position: fixed; | ||||
|     top: 0; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     background: rgba(0, 0, 0, 0.2); | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										
											BIN
										
									
								
								examples/assets/building.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								examples/assets/building.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 22 KiB | 
							
								
								
									
										22
									
								
								examples/entries.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								examples/entries.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| //引入当前工程所有的应用 | ||||
| const install = function(Vue) { | ||||
| 	if (install.installed) return Promise.resolve(); | ||||
| 	else { | ||||
| 		let contexts = require.context('../packages', true, /(\/.+)\/App[^\/]+\.vue$/); | ||||
| 		if (contexts) { | ||||
| 			contexts.keys().map((e) => { | ||||
| 				if (contexts(e).default) { | ||||
| 					Vue.component(contexts(e).default.name, contexts(e).default); | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
| // 判断是否是直接引入文件 | ||||
| if (typeof window !== 'undefined' && window.Vue) { | ||||
| 	install(window.Vue); | ||||
| } | ||||
| export default { | ||||
| 	// 导出的对象必须具有 install,才能被 Vue.use() 方法安装 | ||||
| 	install | ||||
| }; | ||||
							
								
								
									
										31
									
								
								examples/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								examples/main.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| import Vue from 'vue'; | ||||
| import App from './App.vue'; | ||||
| import ui from 'element-ui'; | ||||
| import router from './router/router'; | ||||
| import apps from './entries'; | ||||
| import axios from './router/axios'; | ||||
| import utils from './utils'; | ||||
| import vcUI from 'dvcp-ui'; | ||||
| import dvUI from 'dvcp-dv-ui' | ||||
| import 'dvcp-ui/lib/styles/common.scss'; | ||||
| import 'dvcp-ui/lib/dvcp-ui.css'; | ||||
| import store from './store'; | ||||
| import dataV from '@jiaminghi/data-view'; | ||||
|  | ||||
| Vue.use(dataV); | ||||
|  | ||||
| Vue.use(apps); | ||||
| Vue.use(ui); | ||||
| Vue.use(vcUI); | ||||
| Vue.use(dvUI); | ||||
| //富文本编辑器配置 | ||||
| Vue.config.productionTip = false; | ||||
| Vue.prototype.$axios = axios; | ||||
| Vue.prototype.formatContent = (val) => val.replace(/(\r\n)|(\n)/g, '<br>'); | ||||
| Object.keys(utils).map((e) => (Vue.prototype[e] = utils[e])); | ||||
| utils.$store.init(store); | ||||
| new Vue({ | ||||
| 	router, | ||||
| 	store, | ||||
| 	render: (h) => h(App) | ||||
| }).$mount('#app'); | ||||
							
								
								
									
										71
									
								
								examples/router/autoRoutes.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								examples/router/autoRoutes.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| import store from "../store"; | ||||
|  | ||||
| export default { | ||||
|   routes: () => store.state.apps.map(e => { | ||||
|     return { | ||||
|       ...e, | ||||
|       component: () => import(`../views/apps/${e.entry}`) | ||||
|     } | ||||
|   }), | ||||
|   init() { | ||||
|     //约束正则式 | ||||
|     store.commit("cleanApps") | ||||
|     // 自动化本工程应用 | ||||
|     this.loadApps() | ||||
|   }, | ||||
|   loadApps() { | ||||
|     //新App的自动化格式 | ||||
|     let files = require.context('../../packages', true, /\.(\/.+)\/App[^\/]+\.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$/, '$1'), | ||||
|               entry: 'appEntry' | ||||
|             } | ||||
|         //命名规范入口文件必须以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$/, '$1'), | ||||
|               entry: 'appEntry' | ||||
|             } | ||||
|         //命名规范入口文件必须以App开头 | ||||
|         store.commit("addApp", addApp) | ||||
|       } | ||||
|     }) | ||||
|     let oms = require.context('../../oms', true, /\.(\/.+)\/App[^\/]+\.vue$/) | ||||
|     oms.keys().map(path => { | ||||
|       if (oms(path).default) { | ||||
|         let {name, label} = oms(path).default, | ||||
|             addApp = { | ||||
|               name, label: label || name, | ||||
|               path: path.replace(/\.(\/.+\/App.+)\.vue$/, '$1'), | ||||
|               entry: 'appEntry' | ||||
|             } | ||||
|         //命名规范入口文件必须以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, label: label || name, | ||||
|               path: path.replace(/\.(\/.+\/App.+)\.vue$/, '$1'), | ||||
|               entry: 'appEntry' | ||||
|             } | ||||
|         //命名规范入口文件必须以App开头 | ||||
|         store.commit("addApp", addApp) | ||||
|       } | ||||
|     }) | ||||
|   } | ||||
| } | ||||
							
								
								
									
										17
									
								
								examples/router/axios.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								examples/router/axios.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| import instance from 'dvcp-ui/lib/js/request' | ||||
| import {Message} from 'element-ui' | ||||
|  | ||||
| let baseURLs = { | ||||
|   production: "/", | ||||
|   development: '/lan', | ||||
|   oms: '/oms' | ||||
| } | ||||
| instance.defaults.baseURL = baseURLs[process.env.NODE_ENV] | ||||
| instance.interceptors.request.eject(0); | ||||
| instance.interceptors.request.use(config => { | ||||
|   if (!config.withoutToken && localStorage.getItem("ui-token")) { | ||||
|     config.headers['Authorization'] = ["Bearer", localStorage.getItem("ui-token")].join(" ") | ||||
|   } | ||||
|   return config | ||||
| }, error => Message.error(error)) | ||||
| export default instance | ||||
							
								
								
									
										18
									
								
								examples/router/router.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								examples/router/router.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| import Vue from 'vue' | ||||
| import VueRouter from 'vue-router' | ||||
| import autoRoutes from './autoRoutes' | ||||
|  | ||||
| Vue.use(VueRouter) | ||||
| autoRoutes.init() | ||||
| export default new VueRouter({ | ||||
|   mode: 'history', | ||||
|   hashbang: false, | ||||
|   routes: autoRoutes.routes(), | ||||
|   scrollBehavior(to) { | ||||
|     if (to.hash) { | ||||
|       return { | ||||
|         selector: to.hash | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| }) | ||||
							
								
								
									
										50
									
								
								examples/store/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								examples/store/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| import Vue from 'vue' | ||||
| import Vuex from 'vuex' | ||||
| import preState from 'vuex-persistedstate' | ||||
|  | ||||
| Vue.use(Vuex) | ||||
|  | ||||
| const user = { | ||||
|   state: { | ||||
|     info: {}, | ||||
|     ATime:'' | ||||
|   }, | ||||
|   mutations: { | ||||
|     setUserInfo(state, userInfo) { | ||||
|       state.info = userInfo | ||||
|     }, | ||||
|     SET_TIME(state, pay){ | ||||
|       state.ATime=pay | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| export default new Vuex.Store({ | ||||
|   state: { | ||||
|     dicts: [], | ||||
|     apps: [] | ||||
|   }, | ||||
|   mutations: { | ||||
|     setDicts(state, payload) { | ||||
|       if (payload) { | ||||
|         payload.map(p => { | ||||
|           if (state.dicts.some(d => d.key == p.key)) { | ||||
|             const index = state.dicts.findIndex(d => d.key == p.key) | ||||
|             state.dicts.splice(index, 1) | ||||
|             state.dicts.push(p) | ||||
|           } else { | ||||
|             state.dicts.push(p) | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|     addApp(state, app) { | ||||
|       state.apps.push(app) | ||||
|     }, | ||||
|     cleanApps(state) { | ||||
|       state.apps = [] | ||||
|     } | ||||
|   }, | ||||
|   modules: {user}, | ||||
|   plugins: [preState()] | ||||
| }) | ||||
							
								
								
									
										79
									
								
								examples/utils/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								examples/utils/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| import {MessageBox} from 'element-ui' | ||||
| import store from '../store' | ||||
| import tools from 'dvcp-ui/lib/js/utils' | ||||
|  | ||||
| const addChildParty = (parent, pending) => { | ||||
|   let doBeforeCount = pending.length | ||||
|   parent["children"] = parent["children"] || [] | ||||
|   pending.map((e, index, arr) => { | ||||
|     if (e.partyOrgParentId == parent.partyOrgId) { | ||||
|       parent.children.push(e) | ||||
|       arr.splice(index, 1) | ||||
|       addChildParty(parent, arr) | ||||
|     } | ||||
|   }) | ||||
|   if (parent.children.length == 0) { | ||||
|     delete parent.children | ||||
|   } | ||||
|   if (pending.length > 0 && doBeforeCount > pending.length) { | ||||
|     parent.children.map(c => addChildParty(c, pending)) | ||||
|   } | ||||
| } | ||||
| /** | ||||
|  * 封装提示框 | ||||
|  */ | ||||
|  | ||||
|  | ||||
| const $confirm = (content, options) => { | ||||
|   return MessageBox.confirm(content, { | ||||
|     type: "warning", | ||||
|     confirmButtonText: "确认", | ||||
|     center: true, | ||||
|     title: "提示", | ||||
|     dangerouslyUseHTMLString: true, | ||||
|     ...options | ||||
|   }) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * 封装权限判断方法 | ||||
|  */ | ||||
|  | ||||
|  | ||||
| const $permissions = flag => { | ||||
|   const buttons = store.state.user.info.buttons | ||||
|   if (buttons) return buttons.some(b => b.id == flag || b.permission == flag) | ||||
|   else return false | ||||
| } | ||||
|  | ||||
| const $decimalCalc = (...arr) => { | ||||
|   //确认提升精度 | ||||
|   let decimalLengthes = arr.map(e => { | ||||
|     let index = ("" + e).indexOf(".") | ||||
|     return ("" + e).length - index | ||||
|   }) | ||||
|   let maxDecimal = Math.max(...decimalLengthes), precision = Math.pow(10, maxDecimal) | ||||
|   //计算 | ||||
|   let intArr = arr.map(e => (Number(e) || 0) * precision) | ||||
|   //返回计算值 | ||||
|   return intArr.reduce((t, a) => t + a) / precision | ||||
| } | ||||
| /** | ||||
|  * @param { function } func | ||||
|  | ||||
|  * @param { number } wait 延迟执行毫秒数 | ||||
|  | ||||
|  * @param { boolean } immediate  true 表立即执行,false 表非立即执行 | ||||
|  */ | ||||
|  | ||||
|  | ||||
|  | ||||
| export default { | ||||
|   ...tools, | ||||
|   addChildParty, | ||||
|   $confirm, | ||||
|   $permissions, | ||||
|   $decimalCalc | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										32
									
								
								examples/views/apps/appEntry.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								examples/views/apps/appEntry.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <template> | ||||
|   <section class="appEntry"> | ||||
|     <component v-if="app" :is="app" :instance="$axios" :dict="$dict" :permissions="$permissions"/> | ||||
|     <ai-empty v-else>无法找到应用文件</ai-empty> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|  | ||||
| export default { | ||||
|   name: "appEntry", | ||||
|   label: "应用库-应用", | ||||
|   computed: { | ||||
|     app() { | ||||
|       return this.$route.name | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .appEntry { | ||||
|   width: 100%; | ||||
|   flex: 1; | ||||
|   min-width: 0; | ||||
|   min-height: 0; | ||||
|  | ||||
|   & > * { | ||||
|     height: 100%; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										13
									
								
								examples/views/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								examples/views/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <template> | ||||
|   <router-view /> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: "index" | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped> | ||||
|  | ||||
| </style> | ||||
							
								
								
									
										89
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| { | ||||
|   "name": "cw-webapps", | ||||
|   "version": "2.0.0", | ||||
|   "private": false, | ||||
|   "author": "kubbo", | ||||
|   "main": "lib/cw-webapps.common.js", | ||||
|   "scripts": { | ||||
|     "serve": "vue-cli-service serve", | ||||
|     "serve:oms": "npx cross-env NODE_ENV=oms vue-cli-service serve", | ||||
|     "build": "vue-cli-service build", | ||||
|     "lib": "vue-cli-service build --no-clean --target lib --dest lib packages/index.js&npm unpublish --force&npm publish", | ||||
|     "lib:core": "vue-cli-service build --target lib --dest core/dist core/index.js --name vc-app-core&npm unpublish --force&npm publish", | ||||
|     "lib:project": "node project/build.js", | ||||
|     "lib:sass": "node project/sass.js", | ||||
|     "ui": "npm i dvcp-ui@latest dvcp-dv-ui@latest" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@amap/amap-jsapi-loader": "^1.0.1", | ||||
|     "@jiaminghi/data-view": "^2.10.0", | ||||
|     "dayjs": "^1.8.35", | ||||
|     "dvcp-dv": "^1.0.0", | ||||
|     "dvcp-dv-ui": "^2.0.0", | ||||
|     "dvcp-ui": "^1.42.2", | ||||
|     "echarts": "^5.1.2", | ||||
|     "mp4box": "^0.4.1", | ||||
|     "print-js": "^1.0.63", | ||||
|     "serialize-javascript": "^6.0.0", | ||||
|     "sortablejs": "^1.12.0", | ||||
|     "vue-draggable-resizable": "^2.3.0", | ||||
|     "vue-json-editor": "^1.4.3", | ||||
|     "vue-ruler-tool": "^1.2.4", | ||||
|     "vuedraggable": "^2.24.3" | ||||
|   }, | ||||
|   "publishConfig": { | ||||
|     "registry": "http://192.168.1.87:4873/" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@babel/plugin-proposal-logical-assignment-operators": "^7.10.4", | ||||
|     "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", | ||||
|     "@babel/plugin-proposal-optional-chaining": "^7.10.4", | ||||
|     "@vue/cli-plugin-babel": "^3.6.0", | ||||
|     "@vue/cli-plugin-eslint": "^3.6.0", | ||||
|     "@vue/cli-service": "^3.6.0", | ||||
|     "axios": "^0.19.2", | ||||
|     "babel-eslint": "^10.1.0", | ||||
|     "core-js": "^2.6.11", | ||||
|     "element-ui": "^2.13.2", | ||||
|     "eslint": "^5.16.0", | ||||
|     "eslint-plugin-vue": "^5.0.0", | ||||
|     "image-webpack-loader": "^6.0.0", | ||||
|     "inquirer": "^6.5.2", | ||||
|     "node-sass": "npm:sass@^1.43.4", | ||||
|     "sass-loader": "^7.1.0", | ||||
|     "uglifyjs-webpack-plugin": "^2.2.0", | ||||
|     "v-viewer": "^1.6.4", | ||||
|     "vue": "^2.6.11", | ||||
|     "vue-router": "^3.3.4", | ||||
|     "vue-template-compiler": "^2.6.11", | ||||
|     "vuex": "^3.5.1", | ||||
|     "vuex-persistedstate": "^2.7.1" | ||||
|   }, | ||||
|   "vetur": { | ||||
|     "attributes": "./attributes.json" | ||||
|   }, | ||||
|   "eslintConfig": { | ||||
|     "root": true, | ||||
|     "env": { | ||||
|       "node": true | ||||
|     }, | ||||
|     "extends": [ | ||||
|       "plugin:vue/essential", | ||||
|       "eslint:recommended" | ||||
|     ], | ||||
|     "rules": {}, | ||||
|     "parserOptions": { | ||||
|       "parser": "babel-eslint" | ||||
|     } | ||||
|   }, | ||||
|   "postcss": { | ||||
|     "plugins": { | ||||
|       "autoprefixer": {} | ||||
|     } | ||||
|   }, | ||||
|   "browserslist": [ | ||||
|     "> 1%", | ||||
|     "last 2 versions", | ||||
|     "not ie <= 8" | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										61
									
								
								packages/2.0.5/AppBroadcast/AppBroadcast.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								packages/2.0.5/AppBroadcast/AppBroadcast.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| <template> | ||||
|   <div class="AppBroadcast"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from './components/List' | ||||
| import Add from './components/Add' | ||||
|  | ||||
| export default { | ||||
|   label: '广播播发', | ||||
|   name: 'AppBroadcast', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: 'List', | ||||
|       params: {}, | ||||
|       include: [], | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     Add, | ||||
|     List | ||||
|   }, | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === 'add') { | ||||
|         this.component = 'Add' | ||||
|         this.params = data.params | ||||
|       } | ||||
|  | ||||
|       if (data.type == 'list') { | ||||
|         this.component = 'List' | ||||
|         this.params = data.params | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getList() | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppBroadcast { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										333
									
								
								packages/2.0.5/AppBroadcast/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								packages/2.0.5/AppBroadcast/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,333 @@ | ||||
| <template> | ||||
|   <section style="height: 100%"> | ||||
|     <ai-detail class="Add"> | ||||
|       <!-- 返回按钮 --> | ||||
|       <template #title> | ||||
|         <ai-title title="添加广播" isShowBack isShowBottomBorder @onBackClick="cancel(false)"></ai-title> | ||||
|       </template> | ||||
|  | ||||
|       <template #content> | ||||
|         <el-form :model="formData" :rules="formRules" ref="ruleForm" label-width="150px" label-suffix=":" align-items="center"> | ||||
|           <ai-bar title="基础信息"></ai-bar> | ||||
|           <div class="flex"> | ||||
|             <el-form-item label="播发内容" prop="mediaId"> | ||||
|               <ai-select v-model="formData.mediaId" placeholder="播发内容" clearable :selectList="mediaList"></ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="播放设备" prop="serialNo"> | ||||
|               <ai-select v-model="formData.serialNo" placeholder="播放设备" clearable :selectList="equipmentList"></ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="播发级别" prop="messageLevel"> | ||||
|               <ai-select v-model="formData.messageLevel" placeholder="播发级别" clearable :selectList="$dict.getDict('dlbMessageUrgency')"></ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="播放方式" prop="taskType" class="buildingTypes"> | ||||
|               <el-radio-group v-model="formData.taskType"> | ||||
|                 <el-radio label="0">立即播放</el-radio> | ||||
|                 <el-radio label="1">定时播放</el-radio> | ||||
|               </el-radio-group> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="定时策略" prop="cyclingType" v-if="formData.taskType != 0"> | ||||
|               <ai-select v-model="formData.cyclingType" placeholder="定时策略" clearable :selectList="$dict.getDict('dlbDyclingType')"></ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="播放天数" prop="checkList" class="buildingTypes" v-if="formData.taskType != 0 && formData.cyclingType == 2"> | ||||
|               <el-checkbox-group v-model="formData.checkList"> | ||||
|                 <el-checkbox label="1">每周一</el-checkbox> | ||||
|                 <el-checkbox label="2">每周二</el-checkbox> | ||||
|                 <el-checkbox label="3">每周三</el-checkbox> | ||||
|                 <el-checkbox label="4">每周四</el-checkbox> | ||||
|                 <el-checkbox label="5">每周五</el-checkbox> | ||||
|                 <el-checkbox label="6">每周六</el-checkbox> | ||||
|                 <el-checkbox label="7">每周日</el-checkbox> | ||||
|               </el-checkbox-group> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="播放天数" prop="broadcastDay" v-if="formData.taskType != 0 && formData.cyclingType == 3"> | ||||
|               <el-input v-model="formData.broadcastDay" placeholder="播放天数" clearable size="small" maxlength="4"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="开始日期" prop="startDate" v-if="formData.taskType != 0"> | ||||
|               <el-date-picker v-model="formData.startDate" type="date" placeholder="选择日期" size="small"  value-format="yyyy-MM-dd"></el-date-picker> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="开始时间" prop="startTime" v-if="formData.taskType != 0"> | ||||
|               <el-time-picker v-model="formData.startTime" placeholder="开始时间" size="small" :picker-options="{ start: newDate, minTime: newDate}"  value-format="HH:mm:ss"></el-time-picker> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="结束时间" prop="endTime" v-if="formData.taskType != 0"> | ||||
|               <el-time-picker v-model="formData.endTime" placeholder="结束时间" size="small"  :picker-options="{ start: formData.startTime, minTime: formData.startTime}"  value-format="HH:mm:ss"></el-time-picker> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </el-form> | ||||
|       </template> | ||||
|       <template #footer> | ||||
|         <el-button @click="cancel">取消</el-button> | ||||
|         <el-button type="primary" @click="confirm()">提交</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'Add', | ||||
|   components: {}, | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     instance: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     let startTimePass = (rule, value, callback) => { | ||||
|       if (value) { | ||||
|         var myDate = new Date(); | ||||
|         var time = myDate.getHours() + ':' +  myDate.getMinutes() + ':' + myDate.getSeconds() | ||||
|         if (this.timeToSec(value) - this.timeToSec(time)> 0) { | ||||
|           callback() | ||||
|         } else { | ||||
|           callback(new Error('开始时间要大于当前时间')); | ||||
|         } | ||||
|       } else { | ||||
|         callback(new Error('请选择开始时间')); | ||||
|       } | ||||
|     }; | ||||
|     let endTimePass = (rule, value, callback) => { | ||||
|       if (value) { | ||||
|         if (this.timeToSec(value) - this.timeToSec(this.formData.startTime)> 0) { | ||||
|           callback() | ||||
|         } else { | ||||
|           callback(new Error('结束时间要大于开始时间')); | ||||
|         } | ||||
|       } else { | ||||
|         callback(new Error('请选择结束时间')); | ||||
|       } | ||||
|     } | ||||
|     return { | ||||
|       formData: { | ||||
|         mediaId: '', | ||||
|         serialNo: '', | ||||
|         messageLevel: '', | ||||
|         cyclingType: '', | ||||
|         taskType: '0', | ||||
|         cyclingDate: '', | ||||
|         broadcastDay: '', | ||||
|         startDate: '', | ||||
|         startTime: '', | ||||
|         endTime: '', | ||||
|         checkList: [] | ||||
|       }, | ||||
|       formRules: { | ||||
|         mediaId: [ | ||||
|           { required: true, message: '请选择播发内容', trigger: 'change' } | ||||
|         ], | ||||
|         serialNo: [ | ||||
|           { required: true, message: '请选择播放设备', trigger: 'change' } | ||||
|         ], | ||||
|         messageLevel: [ | ||||
|           { required: true, message: '请选择播发级别', trigger: 'change' } | ||||
|         ], | ||||
|         cyclingType: [ | ||||
|           { required: true, message: '请选择定时策略', trigger: 'change' } | ||||
|         ], | ||||
|         taskType: [ | ||||
|           { required: true, message: '请选择播放方式', trigger: 'change' } | ||||
|         ], | ||||
|         broadcastDay: [ | ||||
|           { required: true, message: '请输入播放天数', trigger: 'change' } | ||||
|         ], | ||||
|         startDate: [ | ||||
|           { required: true, message: '请选择开始日期', trigger: 'change' } | ||||
|         ], | ||||
|         startTime: [ | ||||
|           { required: true, validator: startTimePass, trigger: 'change' } | ||||
|         ], | ||||
|         endTime: [ | ||||
|           { required: true, validator: endTimePass, trigger: 'change' } | ||||
|         ], | ||||
|         checkList: [ | ||||
|           { required: true, message: '播放天数', trigger: 'change' } | ||||
|         ], | ||||
|       }, | ||||
|       mediaList: [], | ||||
|       equipmentList: [] | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     isEdit() { | ||||
|       return !!this.params.id | ||||
|     }, | ||||
|     newDate() { | ||||
|       var myDate = new Date(); | ||||
|       var time = myDate.getHours() + ':' +  myDate.getMinutes() + ':' + myDate.getSeconds() | ||||
|       return time | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load('dlbMessageUrgency', 'dlbBroadTaskType', 'dlbDyclingType').then(() => { | ||||
|       this.getEquipmentList() | ||||
|     }) | ||||
|   }, | ||||
|   methods: { | ||||
|     getMediaList() { | ||||
|       this.instance.post(`/app/appdlbresource/list?current=1&size=10000`).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.mediaList = [] | ||||
|           if(res.data && res.data.records.length) { | ||||
|             res.data.records.map((item) => { | ||||
|               let info = { | ||||
|                 dictName: item.name, | ||||
|                 dictValue: item.id | ||||
|               } | ||||
|               this.mediaList.push(info) | ||||
|             }) | ||||
|           } | ||||
|           if(this.params.id) { | ||||
|             this.getDetail() | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getEquipmentList() { | ||||
|       this.instance.post(`/app/appdlbquipment/getDlbDeviceList?current=1&size=10000&devStatus=5&keyword=`).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.equipmentList = [] | ||||
|           if(res.data && res.data.records.length) { | ||||
|             res.data.records.map((item) => { | ||||
|               let info = { | ||||
|                 dictName: item.deviceName, | ||||
|                 dictValue: item.serialNo | ||||
|               } | ||||
|               this.equipmentList.push(info) | ||||
|             }) | ||||
|           } | ||||
|           this.getMediaList() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     confirm() { | ||||
|       this.$refs['ruleForm'].validate((valid) => { | ||||
|         if (valid) { | ||||
|           if(this.formData.checkList.length) { | ||||
|             this.formData.cyclingDate = this.formData.checkList.join(',') | ||||
|           } | ||||
|           this.formData.coverageType = '4' | ||||
|           this.formData.id = '' | ||||
|           this.instance.post(`/app/appzyvideobroadcast/play`, { | ||||
|             ...this.formData, | ||||
|           }) | ||||
|           .then((res) => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('提交成功') | ||||
|               setTimeout(() => { | ||||
|                 this.cancel(true) | ||||
|               }, 1000) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getDetail() { | ||||
|       this.instance.post(`/app/appzyvideobroadcast/queryDetailById?id=${this.params.id}`).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.formData = { | ||||
|             ...res.data, | ||||
|             checkList: [] | ||||
|           } | ||||
|           this.formData.mediaId = String(this.formData.mediaId) | ||||
|           this.formData.cyclingType = String(this.formData.cyclingType) | ||||
|           if(this.formData.cyclingDate) { | ||||
|             this.formData.checkList = this.formData.cyclingDate.split(',') | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     timeToSec(time) { | ||||
|      var s = ""; | ||||
|       var hour = time.split(":")[0]; | ||||
|       var min = time.split(":")[1]; | ||||
|       var second =  time.split(":")[2]; | ||||
|       s = Number(hour * 3600) + Number(min * 60) + Number(second) | ||||
|       return s; | ||||
|     },  | ||||
|     // 返回按钮 | ||||
|     cancel(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: !!isRefresh, | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .Add { | ||||
|   height: 100%; | ||||
|   .ai-detail__title { | ||||
|     background-color: #fff; | ||||
|   } | ||||
|   .ai-detail__content { | ||||
|     .ai-detail__content--wrapper { | ||||
|       .el-form { | ||||
|         background-color: #fff; | ||||
|         padding: 0 60px; | ||||
|         .flex { | ||||
|           display: flex; | ||||
|           flex-wrap: wrap; | ||||
|           justify-content: space-between; | ||||
|           .el-form-item { | ||||
|             width: 48%; | ||||
|           } | ||||
|           .buildingTypes { | ||||
|             width: 100%; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| ::v-deep .mapDialog { | ||||
|   .el-dialog__body { | ||||
|     padding: 0; | ||||
|  | ||||
|     .ai-dialog__content { | ||||
|       padding: 0; | ||||
|     } | ||||
|  | ||||
|     .ai-dialog__content--wrapper { | ||||
|       padding: 0 !important; | ||||
|       position: relative; | ||||
|     } | ||||
|  | ||||
|     #map { | ||||
|       width: 100%; | ||||
|       height: 420px; | ||||
|     } | ||||
|  | ||||
|     .searchPlaceInput { | ||||
|       position: absolute; | ||||
|       width: 250px; | ||||
|       top: 30px; | ||||
|       left: 25px; | ||||
|     } | ||||
|  | ||||
|     #searchPlaceOutput { | ||||
|       position: absolute; | ||||
|       width: 250px; | ||||
|       left: 25px; | ||||
|       height: initial; | ||||
|       top: 80px; | ||||
|       background: white; | ||||
|       z-index: 250; | ||||
|       max-height: 300px; | ||||
|       overflow-y: auto; | ||||
|  | ||||
|       .auto-item { | ||||
|         text-align: left; | ||||
|         font-size: 14px; | ||||
|         padding: 8px; | ||||
|         box-sizing: border-box; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										156
									
								
								packages/2.0.5/AppBroadcast/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								packages/2.0.5/AppBroadcast/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | ||||
| <template> | ||||
|   <section class="AppPetitionManage"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="广播播发" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar bottomBorder> | ||||
|           <template slot="left"> | ||||
|             <ai-select v-model="search.messageType" placeholder="媒资类型" clearable | ||||
|                        :selectList="$dict.getDict('dlbResourceType')" | ||||
|                        @change=";(page.current = 1), getList()"></ai-select> | ||||
|             <ai-select v-model="search.messageUrgency" placeholder="级别" clearable | ||||
|                        :selectList="$dict.getDict('dlbMessageUrgency')" | ||||
|                        @change=";(page.current = 1), getList()"></ai-select> | ||||
|           </template> | ||||
|           <template slot="right"> | ||||
|             <el-input v-model="search.messageName" size="small" placeholder="媒资名称" clearable | ||||
|                       @keyup.enter.native=";(page.current = 1), getList()" | ||||
|                       @clear=";(page.current = 1), (search.messageName = ''), getList()" | ||||
|                       suffix-icon="iconfont iconSearch"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-search-bar class="ai-search-ba mar-t10"> | ||||
|           <template slot="left"> | ||||
|             <el-button icon="iconfont iconAdd" type="primary" size="small" @click="onAdd('')">添加</el-button> | ||||
|             <!-- <el-button icon="iconfont iconDelete" size="small" @click="removeAll" :disabled="ids.length == 0">删除 </el-button> --> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" :dict="dict" | ||||
|                   :current.sync="page.current" :size.sync="page.size" @getList="getList" | ||||
|                   @selection-change="(v) => (ids = v.map((e) => e.id))"> | ||||
|           <el-table-column slot="options" label="操作" align="center" width="180" fixed="right"> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <el-button type="text" @click="onAdd(row.broadcastId)">复制</el-button> | ||||
|               <el-button type="text" @click="cancel(row.broadcastId)" | ||||
|                          v-if="row.broadcastStatus == 0 || row.broadcastStatus == 1 || row.broadcastStatus == 2">撤回 | ||||
|               </el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'List', | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     instance: Function, | ||||
|     params: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       isAdd: false, | ||||
|       page: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|       }, | ||||
|       total: 0, | ||||
|       search: { | ||||
|         messageName: '', | ||||
|         messageType: '', | ||||
|         messageUrgency: '', | ||||
|       }, | ||||
|       id: '', | ||||
|       ids: [], | ||||
|       colConfigs: [ | ||||
|         {prop: 'messageName', label: '媒资名称', width: 400}, | ||||
|         {prop: 'messageType', label: '媒资类型', align: 'center', dict: "dlbResourceType"}, | ||||
|         {prop: 'messageUrgency', label: '级别', align: 'center', dict: "dlbMessageUrgency"}, | ||||
|         {prop: 'taskType', label: '播发方式', align: 'center', dict: "dlbBroadTaskType"}, | ||||
|         {prop: 'startDate', label: '开始时间', align: 'center'}, | ||||
|         {prop: 'broadcastStatus', label: '状态', align: 'center', dict: "dlbBroadcastStatus"}, | ||||
|         {prop: 'areaName', label: '地区', align: 'center'}, | ||||
|         {prop: 'createUserName', label: '创建人', align: 'center'}, | ||||
|         {slot: 'options'}, | ||||
|       ], | ||||
|       tableData: [], | ||||
|       areaId: '', | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     param() { | ||||
|       return { | ||||
|         ...this.search, | ||||
|         areaId: this.user.info?.areaId, | ||||
|         ids: this.ids, | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     this.areaId = this.user.info.areaId | ||||
|     this.dict.load('dlbResourceType', 'dlbMessageUrgency', 'dlbBroadTaskType', 'dlbBroadcastStatus', 'dlbMessageUrgency').then(() => { | ||||
|       this.getList() | ||||
|     }) | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getList() { | ||||
|       this.instance.post(`/app/appzyvideobroadcast/getBroadcastRecords`, null, { | ||||
|         params: { | ||||
|           ...this.page, | ||||
|           ...this.search, | ||||
|         }, | ||||
|       }) | ||||
|       .then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.tableData = res.data.records | ||||
|           this.total = parseInt(res.data.total) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     onAdd(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'add', | ||||
|         params: { | ||||
|           id: id || '' | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     cancel(id) { | ||||
|       this.$confirm('确定撤回该广播?').then(() => { | ||||
|         this.instance.post(`/app/appzyvideobroadcast/getBroadcastRecall?broadcastId=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('撤回成功!') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     removeAll() { | ||||
|       var id = this.ids.join(',') | ||||
|       this.remove(id) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppPetitionManage { | ||||
|   height: 100%; | ||||
|  | ||||
|   .mar-t10 { | ||||
|     margin-top: 10px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										68
									
								
								packages/2.0.5/AppBuildManage/AppBuildManage.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								packages/2.0.5/AppBuildManage/AppBuildManage.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| <template> | ||||
|   <div class="AppBuildManage"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from './components/List' | ||||
| import Add from './components/Add' | ||||
| import BuildMsg from './components/BuildMsg' | ||||
|  | ||||
| export default { | ||||
|   label: '楼栋管理', | ||||
|   name: 'AppBuildManage', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: 'List', | ||||
|       params: {}, | ||||
|       include: [], | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     Add, | ||||
|     List, | ||||
|     BuildMsg, | ||||
|   }, | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === 'add') { | ||||
|         this.component = 'Add' | ||||
|         this.params = data.params | ||||
|       } | ||||
|  | ||||
|       if (data.type === 'buildmsg') { | ||||
|         this.component = 'BuildMsg' | ||||
|         this.params = { ...data.params } | ||||
|       } | ||||
|  | ||||
|       if (data.type == 'list') { | ||||
|         this.component = 'List' | ||||
|         this.params = data.params | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getList() | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppBuildManage { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										394
									
								
								packages/2.0.5/AppBuildManage/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										394
									
								
								packages/2.0.5/AppBuildManage/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,394 @@ | ||||
| <template> | ||||
|   <section style="height: 100%"> | ||||
|     <ai-detail class="Add"> | ||||
|       <!-- 返回按钮 --> | ||||
|       <template #title> | ||||
|         <ai-title :title="isEdit ? '编辑楼栋信息' : '添加楼栋'" isShowBack isShowBottomBorder @onBackClick="cancel(false)"></ai-title> | ||||
|       </template> | ||||
|  | ||||
|       <template #content> | ||||
|         <el-form :model="formData" :rules="formRules" ref="ruleForm" label-width="150px" label-suffix=":" align-items="center"> | ||||
|           <!-- 小区名称 --> | ||||
|           <ai-bar title="基础信息"></ai-bar> | ||||
|           <el-form-item label="小区名称" prop="communityName" class="line" ref="communityNameContent"> | ||||
|             <!-- 选择小区 --> | ||||
|             <ai-select v-if="instance" :instance="instance" v-model="formData.communityId" action="/app/appcommunityinfo/listAll" :prop="{ label: 'communityName' }"></ai-select> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <div class="flex"> | ||||
|             <!-- 楼栋号 --> | ||||
|             <el-form-item label="楼栋号" prop="buildingNumber" :rules="[{ required: true, message: '请输入楼栋号', trigger: 'blur' }]"> | ||||
|               <el-input size="small" v-model="formData.buildingNumber" placeholder="请输入" clearable :disabled="isEdit" /> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 单元数 --> | ||||
|             <el-form-item label="单元数" prop="unitNumber"> | ||||
|               <el-input size="small" v-model.number="formData.unitNumber" placeholder="请输入" clearable :disabled="isEdit" /> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 起始计数层数 --> | ||||
|             <el-form-item label="起始计数层数" prop="layerStart"> | ||||
|               <el-input size="small" v-model.number="formData.layerStart" placeholder="请输入" clearable :disabled="isEdit"></el-input> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 最高层数 --> | ||||
|             <el-form-item label="最高层数" prop="layerNumber"> | ||||
|               <el-input size="small" v-model.number="formData.layerNumber" placeholder="请输入" clearable :disabled="isEdit"></el-input> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 起始计数户数 --> | ||||
|             <el-form-item label="起始计数户数" prop="householdStart"> | ||||
|               <el-input size="small" v-model.number="formData.householdStart" placeholder="请输入" clearable :disabled="isEdit"></el-input> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 每层户数 --> | ||||
|             <el-form-item label="每层户数" prop="householdNumber"> | ||||
|               <el-input size="small" v-model.number="formData.householdNumber" placeholder="请输入" clearable :disabled="isEdit"></el-input> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 楼栋长姓名 --> | ||||
|             <el-form-item label="楼栋长姓名" prop="managerName"> | ||||
|               <el-input size="small" v-model="formData.managerName" placeholder="请输入" clearable></el-input> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 楼栋长联系方式 --> | ||||
|             <el-form-item label="楼栋长联系方式" prop="managerPhone"> | ||||
|               <el-input size="small" v-model.number="formData.managerPhone" placeholder="请输入" clearable></el-input> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 房屋类别 --> | ||||
|             <el-form-item label="房屋类别" prop="buildingType" class="buildingTypes"> | ||||
|               <el-radio-group v-model="formData.buildingType"> | ||||
|                 <el-radio label="0">单元(公寓)楼</el-radio> | ||||
|                 <el-radio label="1">筒子楼</el-radio> | ||||
|                 <el-radio label="2">别墅</el-radio> | ||||
|  | ||||
|                 <el-radio label="3">自建楼</el-radio> | ||||
|                 <el-radio label="4">平房</el-radio> | ||||
|                 <el-radio label="5">高层公共建筑</el-radio> | ||||
|  | ||||
|                 <el-radio label="6">商住两用</el-radio> | ||||
|                 <el-radio label="7">其它</el-radio> | ||||
|               </el-radio-group> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 楼栋经度坐标 --> | ||||
|             <el-form-item label="楼栋经度坐标" prop="lng"> | ||||
|               <el-input size="small" v-model="formData.lng" placeholder="请输入" clearable></el-input> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 楼栋纬度坐标 --> | ||||
|             <el-form-item label="楼栋纬度坐标" prop="lat"> | ||||
|               <el-input size="small" v-model="formData.lat" placeholder="请输入" clearable></el-input> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <!-- 地图位置 --> | ||||
|             <el-form-item label="地图位置" prop="lat"> | ||||
|               <el-button @click="showMap = true">地图标绘</el-button> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </el-form> | ||||
|       </template> | ||||
|  | ||||
|       <!-- 底部按钮 --> | ||||
|       <template #footer> | ||||
|         <el-button @click="cancel">取消</el-button> | ||||
|         <el-button type="primary" @click="confirm()">提交</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|     <ai-dialog title="地图" :visible.sync="showMap" @opened="getCorpLocation" width="800px" class="mapDialog" @onConfirm="selectMap"> | ||||
|       <div id="map"></div> | ||||
|       <el-form label-width="80px" style="padding: 10px 20px 0 20px;"> | ||||
|         <el-row type="flex" justify="space-between"> | ||||
|           <el-form-item label="经度"> | ||||
|             <el-input disabled size="small" v-model="placeDetail.lng"></el-input> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="纬度"> | ||||
|             <el-input disabled size="small" v-model="placeDetail.lat"></el-input> | ||||
|           </el-form-item> | ||||
|         </el-row> | ||||
|       </el-form> | ||||
|       <el-input id="searchPlaceInput" size="medium" class="searchPlaceInput" clearable v-model="searchPlace" autocomplete="on" @change="placeSearch.search(searchPlace)" placeholder="请输入关键字"> | ||||
|         <el-button type="primary" slot="append" @click="placeSearch.search(searchPlace)">搜索</el-button> | ||||
|       </el-input> | ||||
|       <div id="searchPlaceOutput" /> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from 'vuex' | ||||
| import AMapLoader from '@amap/amap-jsapi-loader' | ||||
|  | ||||
| export default { | ||||
|   name: 'Add', | ||||
|   components: {}, | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     instance: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       formData: { | ||||
|         communityName: '', | ||||
|         buildingNumber: '', | ||||
|         unitNumber: '', | ||||
|         layerStart: '1', | ||||
|         layerNumber: '', | ||||
|         householdStart: '1', | ||||
|         householdNumber: '', | ||||
|         managerName: '', | ||||
|         managerPhone: '', | ||||
|         lng: '', | ||||
|         lat: '', | ||||
|         id: '', // 小区编号 | ||||
|         buildingType: '0', | ||||
|         communityId: '', | ||||
|       }, | ||||
|       formRules: { | ||||
|         unitNumber: [ | ||||
|           { required: true, message: '请输入单元数', trigger: 'change' }, | ||||
|           { | ||||
|             validator: (r, v, cb) => (!v || /^[1-9]\d*|0$/g.test(v) ? cb() : cb('请输入正整数')), | ||||
|           }, | ||||
|         ], | ||||
|         layerStart: [ | ||||
|           { required: true, message: '请输入起始计数层数', trigger: 'change' }, | ||||
|           { | ||||
|             validator: (r, v, cb) => (!v || /^[1-9]\d*|0$/g.test(v) ? cb() : cb('请输入正整数')), | ||||
|           }, | ||||
|         ], | ||||
|  | ||||
|         layerNumber: [ | ||||
|           { required: true, message: '请输入最高层数', trigger: 'change' }, | ||||
|           { | ||||
|             validator: (r, v, cb) => (!v || /^[1-9]\d*|0$/g.test(v) ? cb() : cb('请输入正整数')), | ||||
|           }, | ||||
|         ], | ||||
|         householdStart: [ | ||||
|           { required: true, message: '请输入起始计数户数', trigger: 'change' }, | ||||
|           { | ||||
|             validator: (r, v, cb) => (!v || /^[1-9]\d*|0$/g.test(v) ? cb() : cb('请输入正整数')), | ||||
|           }, | ||||
|         ], | ||||
|  | ||||
|         householdNumber: [ | ||||
|           { required: true, message: '请输入最高层数', trigger: 'change' }, | ||||
|           { | ||||
|             validator: (r, v, cb) => (!v || /^[1-9]\d*|0$/g.test(v) ? cb() : cb('请输入正整数')), | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|       plot: [], | ||||
|       dialogVisible: false, | ||||
|       treeData: [], | ||||
|       map: null, | ||||
|       placeDetail: { | ||||
|         lng: '', | ||||
|         lat: '', | ||||
|       }, | ||||
|       showMap: false, | ||||
|       searchPlace: '', | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     isEdit() { | ||||
|       return !!this.params.id | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     this.formData.communityId = this.params.communityId | ||||
|     this.getListinfo() | ||||
|   }, | ||||
|   methods: { | ||||
|     selectMap() { | ||||
|       this.formData.lng = this.placeDetail.lng | ||||
|       this.formData.lat = this.placeDetail.lat | ||||
|       this.showMap = false | ||||
|     }, | ||||
|     getCorpLocation() { | ||||
|       this.instance.post('/app/appdvcpconfig/getCorpLocation').then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.initMap(res.data) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     initMap({ lng, lat }) { | ||||
|       AMapLoader.load({ | ||||
|         key: '54a02a43d9828a8f9cd4f26fe281e74e', | ||||
|         version: '2.0', | ||||
|         plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete', 'AMap.Geocoder'], | ||||
|       }).then((AMap) => { | ||||
|         this.placeDetail.lng = this.formData.lng | ||||
|         this.placeDetail.lat = this.formData.lat | ||||
|         this.map = new AMap.Map('map', { | ||||
|           resizeEnable: true, | ||||
|           zooms: [6, 20], | ||||
|           center: [lng, lat], | ||||
|           zoom: 11, | ||||
|         }) | ||||
|         this.placeSearch = new AMap.PlaceSearch({ map: this.map }) | ||||
|         new AMap.AutoComplete({ | ||||
|           input: 'searchPlaceInput', | ||||
|           output: 'searchPlaceOutput', | ||||
|         }).on('select', (e) => { | ||||
|           if (e?.poi) { | ||||
|             this.placeSearch.setCity(e.poi.adcode) | ||||
|             this.movePosition(e.poi.location) | ||||
|           } | ||||
|         }) | ||||
|         this.map.on('click', (e) => { | ||||
|           new AMap.Geocoder().getAddress(e.lnglat, (sta, res) => { | ||||
|             if (res?.regeocode) { | ||||
|               this.placeDetail = { | ||||
|                 lng: e.lnglat?.lng, | ||||
|                 lat: e.lnglat?.lat, | ||||
|                 address: res.regeocode.formattedAddress, | ||||
|               } | ||||
|             } | ||||
|           }) | ||||
|           this.movePosition(e.lnglat) | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     movePosition(center) { | ||||
|       if (this.map) { | ||||
|         this.map.clearMap() | ||||
|         this.map.panTo(center) | ||||
|         this.map.add([ | ||||
|           new AMap.Marker({ | ||||
|             position: center, | ||||
|             clickable: true, | ||||
|           }), | ||||
|         ]) | ||||
|         this.map.setFitView() | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     getListinfo() { | ||||
|       return this.instance | ||||
|         .post('/app/appcommunitybuildinginfo/queryDetailById', null, { | ||||
|           params: { | ||||
|             id: this.params.id, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res.data) { | ||||
|             this.formData = res.data | ||||
|           } | ||||
|         }) | ||||
|     }, | ||||
|  | ||||
|     confirm() { | ||||
|       this.$refs['ruleForm'].validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.instance | ||||
|             .post(`/app/appcommunitybuildinginfo/addOrUpdate`, { | ||||
|               ...this.formData, | ||||
|             }) | ||||
|             .then((res) => { | ||||
|               if (res.code == 0) { | ||||
|                 this.$message.success('提交成功') | ||||
|                 setTimeout(() => { | ||||
|                   this.cancel(true) | ||||
|                 }, 1000) | ||||
|               } | ||||
|             }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 返回按钮 | ||||
|     cancel(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: !!isRefresh, | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     communityNameContent: { | ||||
|       deep: true, | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .Add { | ||||
|   height: 100%; | ||||
|   .ai-detail__title { | ||||
|     background-color: #fff; | ||||
|   } | ||||
|   .ai-detail__content { | ||||
|     .ai-detail__content--wrapper { | ||||
|       .el-form { | ||||
|         background-color: #fff; | ||||
|         padding: 0 60px; | ||||
|         .flex { | ||||
|           display: flex; | ||||
|           flex-wrap: wrap; | ||||
|           justify-content: space-between; | ||||
|           .el-form-item { | ||||
|             width: 48%; | ||||
|           } | ||||
|           .buildingTypes { | ||||
|             width: 100%; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| ::v-deep .mapDialog { | ||||
|   .el-dialog__body { | ||||
|     padding: 0; | ||||
|  | ||||
|     .ai-dialog__content { | ||||
|       padding: 0; | ||||
|     } | ||||
|  | ||||
|     .ai-dialog__content--wrapper { | ||||
|       padding: 0 !important; | ||||
|       position: relative; | ||||
|     } | ||||
|  | ||||
|     #map { | ||||
|       width: 100%; | ||||
|       height: 420px; | ||||
|     } | ||||
|  | ||||
|     .searchPlaceInput { | ||||
|       position: absolute; | ||||
|       width: 250px; | ||||
|       top: 30px; | ||||
|       left: 25px; | ||||
|     } | ||||
|  | ||||
|     #searchPlaceOutput { | ||||
|       position: absolute; | ||||
|       width: 250px; | ||||
|       left: 25px; | ||||
|       height: initial; | ||||
|       top: 80px; | ||||
|       background: white; | ||||
|       z-index: 250; | ||||
|       max-height: 300px; | ||||
|       overflow-y: auto; | ||||
|  | ||||
|       .auto-item { | ||||
|         text-align: left; | ||||
|         font-size: 14px; | ||||
|         padding: 8px; | ||||
|         box-sizing: border-box; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										750
									
								
								packages/2.0.5/AppBuildManage/components/BuildMsg.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										750
									
								
								packages/2.0.5/AppBuildManage/components/BuildMsg.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,750 @@ | ||||
| <template> | ||||
|   <ai-list class="BuildMsg"> | ||||
|     <!-- 标题 --> | ||||
|     <template #title> | ||||
|       <ai-title :title="params.communityName + '-' + params.buildingNumber + '号楼房屋信息'" isShowBack isShowBottomBorder | ||||
|                 @onBackClick="cancel(false)"></ai-title> | ||||
|     </template> | ||||
|     <template #content> | ||||
|       <!-- 性别下拉选择框 --> | ||||
|       <ai-search-bar> | ||||
|         <template #left> | ||||
|           <ai-select v-model="search.livingStatus" placeholder="房屋状态" clearable @change=";(page.current = 1), getList()" | ||||
|                      :selectList="dict.getDict('houselivingStatus')"></ai-select> | ||||
|  | ||||
|           <ai-select v-model="search.existFlow" placeholder="有无流动人口" clearable @change=";(page.current = 1), getList()" | ||||
|                      :selectList="dict.getDict('yesOrNo')"></ai-select> | ||||
|         </template> | ||||
|  | ||||
|         <template #right> | ||||
|           <el-input v-model="search.houseCode" size="small" placeholder="请输入户号/户主" clearable | ||||
|                     @keyup.enter.native=";(page.current = 1), getList()" | ||||
|                     @clear=";(page.current = 1), (search.houseCode = ''), getList()" suffix-icon="iconfont iconSearch"/> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|  | ||||
|       <ai-search-bar> | ||||
|         <template #left> | ||||
|           <div style="height: 32px"/> | ||||
|         </template> | ||||
|  | ||||
|         <template #right> | ||||
|           <ai-import :instance="instance" :dict="dict" type="appcommunityhouseinfo" :importParams="houseImpParam" name="房屋信息" | ||||
|                      @success="getList()"> | ||||
|             <el-button icon="iconfont iconImport">导入房屋信息</el-button> | ||||
|           </ai-import> | ||||
|           <ai-download :instance="instance" url="/app/appcommunityhouseinfo/listExport" :params="houseExpParam" | ||||
|                        fileName="房屋信息" style="margin-right: 10px"> | ||||
|             <el-button icon="iconfont iconExported">导出房屋信息</el-button> | ||||
|           </ai-download> | ||||
|           <ai-import :instance="instance" :dict="dict" type="appcommunityhouseresident" :importParams="houseImpParam" name="人口信息" | ||||
|                      @success="getList()"> | ||||
|             <el-button icon="iconfont iconImport">导入人口信息</el-button> | ||||
|           </ai-import> | ||||
|           <ai-download :instance="instance" url="/app/appcommunityhouseresident/listExport" :params="houseExpParam" | ||||
|                        fileName="人口信息"> | ||||
|             <el-button icon="iconfont iconExported">导出人口信息</el-button> | ||||
|           </ai-download> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|  | ||||
|       <ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" ref="aitableex" | ||||
|                 :current.sync="page.current" :size.sync="page.size" @getList="getList" | ||||
|                 @selection-change="(v) => (ids = v.map((e) => e.id))"> | ||||
|         <el-table-column slot="owner" label="房主" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <span v-for="(item, i) in row.owner" :key="i" v-if="item.name"> | ||||
|               <span v-if="i < 2" style="margin-right: 5px;"> | ||||
|                 {{ item.name }} | ||||
|               </span> | ||||
|             </span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|  | ||||
|         <el-table-column slot="owner" label="联系方式" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <span v-for="(item, i) in row.owner" :key="i" v-if="item.phone"> | ||||
|               <span v-if="i < 1"> | ||||
|                 {{ item.phone }} | ||||
|               </span> | ||||
|             </span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|  | ||||
|         <el-table-column slot="livingStatus" label="房屋状态" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             {{ dict.getLabel('houselivingStatus', row.livingStatus) }} | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|  | ||||
|         <el-table-column slot="owner" label="流动人口" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <span>{{ row.existFlow == 1 ? '有' : '无' }}</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|  | ||||
|         <el-table-column slot="options" label="操作" align="center" fixed="right" width="130"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <el-button type="text" @click="toEdit(row.id, 'edit')">编辑</el-button> | ||||
|             <el-button type="text" @click="toEdit(row.id, 'detail')">详情</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|  | ||||
|       <ai-dialog :title="isEdit ? '编辑居民户' : '居民户详情'" :visible.sync="dialogVisible" width="800px" customFooter> | ||||
|         <ai-wrapper label> | ||||
|           <div class="bulidmsg"> | ||||
|             <span class="icon"></span> | ||||
|             <span class="bulidtext">房屋信息</span> | ||||
|           </div> | ||||
|  | ||||
|           <ai-info-item label="所属社区"> | ||||
|             {{ forms.areaName }} | ||||
|           </ai-info-item> | ||||
|  | ||||
|           <ai-info-item label="房屋地址"> | ||||
|             {{ forms.createAddress }} | ||||
|           </ai-info-item> | ||||
|  | ||||
|           <ai-info-item label="房屋类型"> | ||||
|             {{ dict.getLabel('communityBuildingType', forms.buildingType) }} | ||||
|           </ai-info-item> | ||||
|  | ||||
|           <template v-if="!isEdit"> | ||||
|             <ai-info-item label="房屋面积" prop="houseArea" class="line"> | ||||
|               <span>{{ forms.houseArea }}</span | ||||
|               > <span v-if="forms.houseArea">m²</span> | ||||
|             </ai-info-item> | ||||
|  | ||||
|             <ai-info-item label="居住现状" prop="livingStatus"> | ||||
|               <span>{{ dict.getLabel('houselivingStatus', forms.livingStatus) }}</span> | ||||
|             </ai-info-item> | ||||
|  | ||||
|             <ai-info-item label="房屋用途" prop="houseUse"> | ||||
|               <span>{{ dict.getLabel('houseUseStatus', forms.houseUse) }}</span> | ||||
|             </ai-info-item> | ||||
|  | ||||
|             <ai-info-item label="承租情况" prop="leaseSituation"> | ||||
|               <span>{{ dict.getLabel('houseLeaseSituation', forms.leaseSituation) }}</span> | ||||
|             </ai-info-item> | ||||
|  | ||||
|             <ai-info-item label="起租日期" prop="startDate"> | ||||
|               {{ $dateFormat(forms.startDate) }} | ||||
|             </ai-info-item> | ||||
|  | ||||
|             <ai-info-item label="备案证明" prop="isFilingCertificate"> | ||||
|               <span>{{ dict.getLabel('isFilingCertificateStatus', forms.isFilingCertificate) }}</span> | ||||
|             </ai-info-item> | ||||
|           </template> | ||||
|         </ai-wrapper> | ||||
|  | ||||
|         <el-form v-if="isEdit" :model="forms" ref="ruleForm" label-width="100px" label-suffix=":" align-items="center" | ||||
|                  size="small"> | ||||
|           <template> | ||||
|             <el-form-item label="房屋面积" prop="houseArea" class="house"> | ||||
|               <el-input v-model="forms.houseArea" type="text" size="small" placeholder="请输入" suffix="m²"> | ||||
|                 <template slot="suffix">m²</template> | ||||
|               </el-input> | ||||
|             </el-form-item> | ||||
|  | ||||
|             <div class="family-hose"> | ||||
|               <el-form-item label="居住现状"> | ||||
|                 <el-radio-group v-model="forms.livingStatus"> | ||||
|                   <el-radio label="0">自用</el-radio> | ||||
|                   <el-radio label="1">出租</el-radio> | ||||
|                   <el-radio label="2">闲置</el-radio> | ||||
|                 </el-radio-group> | ||||
|               </el-form-item> | ||||
|  | ||||
|               <el-form-item label="房屋用途"> | ||||
|                 <el-radio-group v-model="forms.houseUse"> | ||||
|                   <el-radio label="0">居住</el-radio> | ||||
|                   <el-radio label="1">闲置</el-radio> | ||||
|                   <el-radio label="2">经营</el-radio> | ||||
|                 </el-radio-group> | ||||
|               </el-form-item> | ||||
|             </div> | ||||
|  | ||||
|             <div class="family-hose"> | ||||
|               <el-form-item label="承租情况" prop="leaseSituation"> | ||||
|                 <ai-select v-model="forms.leaseSituation" placeholder="请选择" clearable | ||||
|                            @change=";(page.current = 1), getList()" :selectList="dict.getDict('houseLeaseSituation')" | ||||
|                            size="small"></ai-select> | ||||
|               </el-form-item> | ||||
|  | ||||
|               <el-form-item label="起租日期" prop="startDate"> | ||||
|                 <el-date-picker v-model="forms.startDate" type="date" placeholder="选择日期" size="small" | ||||
|                                 value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker> | ||||
|               </el-form-item> | ||||
|             </div> | ||||
|  | ||||
|             <el-form-item label="备案证明" prop="isFilingCertificate"> | ||||
|               <el-radio-group v-model="forms.isFilingCertificate"> | ||||
|                 <el-radio label="0">有租赁房备案证明</el-radio> | ||||
|                 <el-radio label="1">无租赁房备案证明</el-radio> | ||||
|               </el-radio-group> | ||||
|             </el-form-item> | ||||
|           </template> | ||||
|         </el-form> | ||||
|         <!-- 房主信息 --> | ||||
|         <div class="table"> | ||||
|           <div class="msg"> | ||||
|             <b class="house-msg"> | ||||
|               <span class="icon"></span> | ||||
|               <span class="msg">房主信息</span> | ||||
|             </b> | ||||
|  | ||||
|             <div class="button"> | ||||
|               <ai-person-select :instance="instance" @selectPerson="getOwners" ref="getOwner" :chooseUserList="owners" | ||||
|                                 :isMultiple="true" v-if="isEdit"/> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           <ai-table :tableData="owners" :col-configs="owner" ref="aitableex"> | ||||
|             <el-table-column slot="owner" label="居民类型" align="center"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 {{ dict.getLabel('BulidResidentType', row.residentType) }} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="owner" label="特殊人群" align="center" v-if="!isEdit"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 {{ row.tips }} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="owner" label="与户主关系" align="center" v-if="isEdit"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 <ai-select v-model="row.relation" placeholder="与户主关系" clearable | ||||
|                            :selectList="$dict.getDict('householdRelation')"></ai-select> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="owner" label="与户主关系" align="center" v-if="!isEdit"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 {{ dict.getLabel('householdRelation', row.relation) }} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="options" label="操作" align="center" v-if="isEdit"> | ||||
|               <template slot-scope="scope"> | ||||
|                 <el-button type="text" @click="remove(scope.$index, 'owners')">删除</el-button> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </div> | ||||
|  | ||||
|         <!-- 承租人信息 --> | ||||
|         <div class="table"> | ||||
|           <div class="msg"> | ||||
|             <b class="house-msg"> | ||||
|               <span class="icon"></span> | ||||
|               <span class="msg">承租人信息</span> | ||||
|             </b> | ||||
|  | ||||
|             <div class="button"> | ||||
|               <ai-person-select :instance="instance" @selectPerson="getRenters" :chooseUserList="renters" | ||||
|                                 :isMultiple="true" v-if="isEdit"/> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           <ai-table :tableData="renters" :col-configs="renter" ref="aitableex"> | ||||
|             <el-table-column slot="renters" label="居民类型" align="center"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 {{ dict.getLabel('BulidResidentType', row.residentType) }} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="renters" label="特殊人群" align="center" v-if="!isEdit"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 {{ row.tips }} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="renters" label="与户主关系" align="center" v-if="isEdit"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 <ai-select v-model="row.relation" placeholder="与户主关系" clearable | ||||
|                            :selectList="$dict.getDict('householdRelation')"></ai-select> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="renters" label="与户主关系" align="center" v-if="!isEdit"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 {{ dict.getLabel('householdRelation', row.relation) }} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="options" label="操作" align="center" v-if="isEdit"> | ||||
|               <template slot-scope="scope"> | ||||
|                 <el-button type="text" @click="remove(scope.$index, 'renters')">删除</el-button> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </div> | ||||
|  | ||||
|         <!-- 实际居住人员 --> | ||||
|         <div class="table"> | ||||
|           <div class="msg"> | ||||
|             <b class="house-msg"> | ||||
|               <span class="icon"></span> | ||||
|               <span class="msg">实际居住人员</span> | ||||
|             </b> | ||||
|  | ||||
|             <div class="button" v-if="isEdit"> | ||||
|               <ai-person-select :instance="instance" @selectPerson="getLives" :isMultiple="true" | ||||
|                                 :chooseUserList="lives"/> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           <ai-table :tableData="lives" :col-configs="live" ref="aitableex"> | ||||
|             <el-table-column slot="lives" label="居民类型" align="center"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 {{ dict.getLabel('BulidResidentType', row.residentType) }} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="lives" label="特殊人群" align="center" v-if="!isEdit"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 {{ row.tips }} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="lives" label="与户主关系" align="center" v-if="isEdit"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 <ai-select v-model="row.relation" placeholder="与户主关系" clearable | ||||
|                            :selectList="$dict.getDict('householdRelation')"></ai-select> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="lives" label="与户主关系" align="center" v-if="!isEdit"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 {{ dict.getLabel('householdRelation', row.relation) }} | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="options" label="操作" align="center" v-if="isEdit"> | ||||
|               <template slot-scope="scope"> | ||||
|                 <el-button type="text" @click="remove(scope.$index, 'lives')">删除</el-button> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </div> | ||||
|  | ||||
|         <span slot="footer" class="dialog-footer"> | ||||
|           <el-button @click="dialogVisible = false">{{ isEdit ? '取消' : '关闭' }}</el-button> | ||||
|           <el-button type="primary" @click="report" v-if="isEdit">确认</el-button> | ||||
|         </span> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: 'BuildMsg', | ||||
|   components: {}, | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     instance: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       id: '', | ||||
|       page: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|       }, | ||||
|       total: 0, | ||||
|       search: { | ||||
|         livingStatus: '', | ||||
|         houseCode: '', | ||||
|       }, | ||||
|       colConfigs: [ | ||||
|         {prop: 'unitNumber', label: '单元', align: 'center'}, | ||||
|         {prop: 'houseCode', label: '户号', align: 'center'}, | ||||
|         {prop: 'livingNumber', label: '住户数', align: 'center'}, | ||||
|         {slot: 'owner', label: '户主', align: 'center'}, | ||||
|         {slot: 'livingStatus', align: 'center'}, | ||||
|         {slot: 'options', label: '操作', align: 'center'}, | ||||
|       ], | ||||
|       tableData: [], | ||||
|       dialogVisible: false, | ||||
|       forms: { | ||||
|         houseArea: '', | ||||
|         livingStatus: 0, | ||||
|         houseUse: 0, | ||||
|         leaseSituation: '', | ||||
|         isFilingCertificate: '', | ||||
|       }, | ||||
|       owners: [], | ||||
|       owner: [ | ||||
|         {prop: 'name', label: '姓名', align: 'center'}, | ||||
|         {prop: 'idNumber', label: '身份证号', align: 'center'}, | ||||
|         {prop: 'phone', label: '联系方式', align: 'center'}, | ||||
|         {slot: 'owner', align: 'center'}, | ||||
|         { | ||||
|           slot: 'relation', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         {slot: 'options', label: '操作', align: 'center'}, | ||||
|       ], | ||||
|       renters: [], | ||||
|       renter: [ | ||||
|         {prop: 'name', label: '姓名', align: 'center'}, | ||||
|         {prop: 'idNumber', label: '身份证号', align: 'center'}, | ||||
|         {prop: 'phone', label: '联系方式', align: 'center'}, | ||||
|         { | ||||
|           slot: 'relation', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         {slot: 'renters', align: 'center'}, | ||||
|         {slot: 'options', label: '操作', align: 'center'}, | ||||
|       ], | ||||
|       lives: [], | ||||
|       live: [ | ||||
|         {prop: 'name', label: '姓名', align: 'center'}, | ||||
|         {prop: 'idNumber', label: '身份证号', align: 'center'}, | ||||
|         {prop: 'phone', label: '联系方式', align: 'center'}, | ||||
|         { | ||||
|           slot: 'relation', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         {slot: 'lives', align: 'center'}, | ||||
|         {slot: 'options', label: '操作', align: 'center'}, | ||||
|       ], | ||||
|       type: '', | ||||
|       ids: '', | ||||
|       buildingId: '', | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     houseImpParam() { | ||||
|       return { | ||||
|         buildingId: this.params.id, | ||||
|       } | ||||
|     }, | ||||
|     houseExpParam() { | ||||
|       return { | ||||
|         buildingId: this.params.id, | ||||
|       } | ||||
|     }, | ||||
|     isEdit() { | ||||
|       return this.type == 'edit' | ||||
|     }, | ||||
|   }, | ||||
|   watch: {}, | ||||
|   created() { | ||||
|     this.dict.load('yesOrNo', 'houselivingStatus', 'houseLeaseSituation', 'isFilingCertificateStatus', 'houseUseStatus', 'BulidResidentType', 'communityBuildingType', 'householdRelation').then(() => { | ||||
|       this.getList() | ||||
|     }) | ||||
|   }, | ||||
|   mounted() { | ||||
|   }, | ||||
|   methods: { | ||||
|     getList() { | ||||
|       this.instance | ||||
|       .post(`/app/appcommunityhouseinfo/list`, null, { | ||||
|         params: { | ||||
|           ...this.page, | ||||
|           ...this.search, | ||||
|           buildingId: this.params.id, | ||||
|         }, | ||||
|       }) | ||||
|       .then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.tableData = res.data.records | ||||
|           this.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 返回按钮 | ||||
|     cancel(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: !!isRefresh, | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 确认增加和编辑 | ||||
|     report() { | ||||
|       this.instance | ||||
|       .post(`/app/appcommunityhouseinfo/update`, { | ||||
|         ...this.forms, | ||||
|         id: this.id, | ||||
|         owner: this.owners, | ||||
|         renter: this.renters, | ||||
|         live: this.lives, | ||||
|       }) | ||||
|       .then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.$message.success('提交成功') | ||||
|  | ||||
|           this.dialogVisible = false | ||||
|           this.getList() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 详情 和 编辑 | ||||
|     toEdit(id, type) { | ||||
|       this.id = id | ||||
|       this.type = type | ||||
|       this.instance.post(`/app/appcommunityhouseinfo/queryDetailById?&id=${id}`).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.forms = res.data | ||||
|  | ||||
|           this.owners = this.forms.owner | ||||
|           this.renters = this.forms.renter | ||||
|           this.lives = this.forms.live | ||||
|         } | ||||
|       }) | ||||
|       this.dialogVisible = true | ||||
|     }, | ||||
|  | ||||
|     // 删除 | ||||
|     remove(index, source) { | ||||
|       this.$confirm('确定删除该数据?').then(() => { | ||||
|         this[source].splice(index, 1) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 选择人员 | ||||
|     getOwners(val) { | ||||
|       let listNew = [] | ||||
|       let newName = [] | ||||
|       for (var i = 0; i < val.length; i++) { | ||||
|         if (newName.indexOf(val[i].name) == -1) { | ||||
|           newName.push(val[i].name) | ||||
|           listNew.push(val[i]) | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       this.owners = listNew | ||||
|     }, | ||||
|  | ||||
|     getRenters(val) { | ||||
|       let listNew = [] | ||||
|       let newName = [] | ||||
|       for (var i = 0; i < val.length; i++) { | ||||
|         if (newName.indexOf(val[i].name) == -1) { | ||||
|           newName.push(val[i].name) | ||||
|           listNew.push(val[i]) | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       this.renters = listNew | ||||
|     }, | ||||
|  | ||||
|     getLives(val) { | ||||
|       let listNew = [] | ||||
|       let newName = [] | ||||
|       for (var i = 0; i < val.length; i++) { | ||||
|         if (newName.indexOf(val[i].name) == -1) { | ||||
|           newName.push(val[i].name) | ||||
|           listNew.push(val[i]) | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       this.lives = listNew | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .BuildMsg { | ||||
|   ::v-deep .ai-list__title { | ||||
|     background-color: #fff; | ||||
|     margin: 0 !important; | ||||
|     padding-left: 20px; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-list__content { | ||||
|     .ai-list__content--right { | ||||
|       .ai-list__content--right-wrapper { | ||||
|         .search-select { | ||||
|           display: flex; | ||||
|           justify-content: space-between; | ||||
|           border-bottom: 1px solid #eee; | ||||
|           padding-bottom: 10px; | ||||
|  | ||||
|           .left { | ||||
|             width: 30%; | ||||
|  | ||||
|             .ai-select { | ||||
|               display: inline-block; | ||||
|             } | ||||
|  | ||||
|             .ai-select:first-child { | ||||
|               margin-right: 15px; | ||||
|             } | ||||
|           } | ||||
|  | ||||
|           .right { | ||||
|             width: 20%; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .bar { | ||||
|           display: flex; | ||||
|           justify-content: space-between; | ||||
|           margin-top: 10px; | ||||
|  | ||||
|           .export { | ||||
|             .ai-import { | ||||
|               display: inline-block; | ||||
|               margin-right: 10px; | ||||
|             } | ||||
|  | ||||
|             .ai-download { | ||||
|               display: inline-block; | ||||
|             } | ||||
|           } | ||||
|  | ||||
|           .import { | ||||
|             .ai-import { | ||||
|               display: inline-block; | ||||
|               margin-right: 10px; | ||||
|             } | ||||
|  | ||||
|             .ai-download { | ||||
|               display: inline-block; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .ai-dialog__wrapper { | ||||
|           background-color: #fff; | ||||
|  | ||||
|           .el-dialog__wrapper { | ||||
|             .el-dialog__body { | ||||
|               .ai-dialog__content { | ||||
|                 .ai-dialog__content--wrapper { | ||||
|                   .ai-wrapper { | ||||
|                     padding-left: 0 !important; | ||||
|  | ||||
|                     .bulidmsg { | ||||
|                       height: 32px; | ||||
|                       line-height: 32px; | ||||
|                       width: 100%; | ||||
|                       margin: 0 0 15px 20px; | ||||
|  | ||||
|                       .icon { | ||||
|                         border-left: 2px solid #2266ff; | ||||
|                       } | ||||
|  | ||||
|                       .bulidtext { | ||||
|                         display: inline-block; | ||||
|                         margin-left: 9px; | ||||
|                         color: #222; | ||||
|                         font-size: 15px; | ||||
|                         font-weight: 800; | ||||
|                       } | ||||
|                     } | ||||
|  | ||||
|                     .create { | ||||
|                       width: 100% !important; | ||||
|  | ||||
|                       .ai-info-item__left { | ||||
|                         width: 78px; | ||||
|                         margin-right: 22px; | ||||
|                       } | ||||
|                     } | ||||
|  | ||||
|                     .Address { | ||||
|                       .ai-info-item__left { | ||||
|                         width: 78px; | ||||
|                         margin-right: 22px; | ||||
|                       } | ||||
|                     } | ||||
|  | ||||
|                     .building { | ||||
|                       padding-left: 40px; | ||||
|  | ||||
|                       .ai-info-item__left { | ||||
|                         width: 78px; | ||||
|                         margin-right: 22px; | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|  | ||||
|                   .el-form { | ||||
|                     padding: 20px 0 0 0; | ||||
|  | ||||
|                     .house { | ||||
|                       width: 50%; | ||||
|  | ||||
|                       .el-form-item__content { | ||||
|                         width: 63%; | ||||
|                       } | ||||
|                     } | ||||
|  | ||||
|                     .family-hose { | ||||
|                       display: flex; | ||||
|                       justify-content: space-between; | ||||
|                     } | ||||
|  | ||||
|                     .line { | ||||
|                       width: 50% !important; | ||||
|                       padding-right: 40px; | ||||
|  | ||||
|                       .el-form-item__content { | ||||
|                         .el-input { | ||||
|                           .el-input__suffix { | ||||
|                             color: #666; | ||||
|                             margin-right: 5px; | ||||
|                           } | ||||
|                         } | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|  | ||||
|                   .table { | ||||
|                     padding: 20px 20px 0 20px; | ||||
|  | ||||
|                     .msg { | ||||
|                       display: flex; | ||||
|                       justify-content: space-between; | ||||
|  | ||||
|                       .house-msg { | ||||
|                         height: 32px; | ||||
|                         line-height: 32px; | ||||
|  | ||||
|                         .icon { | ||||
|                           border-left: 2px solid #2266ff; | ||||
|                         } | ||||
|  | ||||
|                         .msg { | ||||
|                           display: inline-block; | ||||
|                           color: #222; | ||||
|                           font-size: 15px; | ||||
|                           font-weight: 800; | ||||
|                           margin-left: 9px; | ||||
|                         } | ||||
|                       } | ||||
|  | ||||
|                       // .button { | ||||
|                       // } | ||||
|                     } | ||||
|  | ||||
|                     .ai-table { | ||||
|                       margin-top: 10px; | ||||
|                       // .el-table { | ||||
|                       // } | ||||
|                       .pagination { | ||||
|                         display: none; | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										312
									
								
								packages/2.0.5/AppBuildManage/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								packages/2.0.5/AppBuildManage/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,312 @@ | ||||
| <template> | ||||
|   <section class="AppPetitionManage"> | ||||
|     <ai-detail> | ||||
|       <!-- 标题 --> | ||||
|       <ai-title slot="title" title="楼栋管理" isShowBottomBorder /> | ||||
|       <template #content> | ||||
|         <ai-tree-menu title="楼栋管理" @search="(v) => $refs.gridTree.filter(v)"> | ||||
|           <el-tree :data="treeData" ref="gridTree" :filter-node-method="handleTreeFilter" @node-click="handleSelectGrid" highlight-current node-key="id" :props="{ label: 'name', children: 'children' }" :default-expanded-keys="[defaultShowNodes]" /> | ||||
|         </ai-tree-menu> | ||||
|  | ||||
|         <div class="flex"> | ||||
|           <ai-search-bar bottomBorder> | ||||
|             <template slot="left"> | ||||
|               <!-- 定位状态 --> | ||||
|               <ai-select v-model="search.locationStatus" placeholder="定位状态" clearable :selectList="$dict.getDict('BuildLocationStatus')" @change=";(page.current = 1), getList()"></ai-select> | ||||
|             </template> | ||||
|  | ||||
|             <!-- 搜索 --> | ||||
|             <template slot="right"> | ||||
|               <el-input v-model="search.managerName" size="small" placeholder="楼栋号/楼长/联系方式" clearable @keyup.enter.native=";(page.current = 1), getList()" @clear=";(page.current = 1), (search.managerName = ''), getList()" suffix-icon="iconfont iconSearch" /> | ||||
|             </template> | ||||
|           </ai-search-bar> | ||||
|  | ||||
|           <ai-search-bar class="ai-search-ba"> | ||||
|             <template slot="left"> | ||||
|               <el-button icon="iconfont iconAdd" type="primary" size="small" @click="onAdd('')" :disabled="!isAdd">添加 </el-button> | ||||
|               <el-button icon="iconfont iconDelete" size="small" @click="removeAll" :disabled="ids.length == 0">删除 </el-button> | ||||
|             </template> | ||||
|  | ||||
|             <!-- 导入导出 --> | ||||
|             <template #right> | ||||
|               <ai-import :instance="instance" :dict="dict" type="appcommunitybuildinginfo" :importParams="{ areaId: user.info && user.info.areaId }" name="楼栋管理" @success="getList()"> | ||||
|                 <el-button icon="iconfont iconImport">导入</el-button> | ||||
|               </ai-import> | ||||
|               <ai-download :instance="instance" url="/app/appcommunitybuildinginfo/listExport" :params="param" fileName="楼栋管理模板" :disabled="tableData.length == 0"> | ||||
|                 <el-button icon="iconfont iconExported" :disabled="tableData.length == 0">导出</el-button> | ||||
|               </ai-download> | ||||
|             </template> | ||||
|           </ai-search-bar> | ||||
|  | ||||
|           <ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" ref="aitableex" style="margin-top: 20px;" :current.sync="page.current" :size.sync="page.size" @getList="getList" @selection-change="(v) => (ids = v.map((e) => e.id))"> | ||||
|             <el-table-column slot="locationStatus" label="定位状态" align="center"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 <span style="color:red" v-if="row.locationStatus == 0">{{ dict.getLabel('BuildLocationStatus', row.locationStatus) }}</span> | ||||
|                 <span style="color:green" v-if="row.locationStatus == 1">{{ dict.getLabel('BuildLocationStatus', row.locationStatus) }}</span> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|  | ||||
|             <el-table-column slot="options" label="操作" align="center" width="300px" fixed="right"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 <el-button type="text" @click="onAdd(row.id)">编辑</el-button> | ||||
|                 <el-button type="text" @click="remove(row.id)">删除</el-button> | ||||
|                 <el-button type="text" @click="toBuildMsg(row)">房屋信息</el-button> | ||||
|                 <el-button type="text" @click="$router.push({ name: '房屋地图', query: { communityId: row.communityId, buildingId: row.id, unitNum: 1, buildingNumber: row.buildingNumber } })"> | ||||
|                   楼栋模型 | ||||
|                 </el-button> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </div> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'List', | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     instance: Function, | ||||
|     params: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       isAdd: false, | ||||
|       page: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|       }, | ||||
|       total: 0, | ||||
|       search: { | ||||
|         locationStatus: '', | ||||
|         managerName: '', | ||||
|       }, | ||||
|       id: '', | ||||
|       ids: [], | ||||
|       colConfigs: [ | ||||
|         { type: 'selection' }, | ||||
|         { | ||||
|           prop: 'communityName', | ||||
|           label: '小区名称', | ||||
|         }, | ||||
|         { | ||||
|           prop: 'buildingNumber', | ||||
|           label: '楼栋号', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         { prop: 'unitNumber', label: '单元数', align: 'center' }, | ||||
|         { | ||||
|           prop: 'layerNumber', | ||||
|           label: '最高层数', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         { prop: 'householdNumber', label: '每层户数', align: 'center' }, | ||||
|         { | ||||
|           prop: 'houseNum', | ||||
|           label: '实有户数', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         { prop: 'residentNum', label: '实有人口', align: 'center' }, | ||||
|         { | ||||
|           prop: 'managerName', | ||||
|           label: '楼栋长名', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         { prop: 'managerPhone', label: '楼栋长联系方式', align: 'center', width: '150' }, | ||||
|         { slot: 'locationStatus' }, | ||||
|         { | ||||
|           slot: 'options', | ||||
|           label: '操作', | ||||
|           align: 'center', | ||||
|         }, | ||||
|       ], | ||||
|       tableData: [], | ||||
|       organizationId: '', | ||||
|       meta: [], | ||||
|       treeData: [], | ||||
|       areaId: '', | ||||
|       communityId: null, | ||||
|       buildingTypeStatus: '', | ||||
|       defaultShowNodes: [], | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     param() { | ||||
|       return { | ||||
|         ...this.search, | ||||
|         communityId: this.communityId, | ||||
|         areaId: this.user.info?.areaId, | ||||
|         ids: this.ids, | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     this.dict.load('BuildLocationStatus').then(() => { | ||||
|       this.getList() | ||||
|       this.getListinfo() | ||||
|     }) | ||||
|   }, | ||||
|  | ||||
|   mounted() {}, | ||||
|  | ||||
|   methods: { | ||||
|     getListinfo() { | ||||
|       return this.instance.post(`/app/appcommunityinfo/queryCommunityTree?id=${this.user.info?.areaId}`).then((res) => { | ||||
|         if (res.data) { | ||||
|           this.treeData = [res.data] | ||||
|           this.$nextTick(() => { | ||||
|             this.defaultShowNodes = this.treeData[0].id | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     getList() { | ||||
|       this.instance | ||||
|         .post(`/app/appcommunitybuildinginfo/list`, null, { | ||||
|           params: { | ||||
|             ...this.page, | ||||
|             ...this.search, | ||||
|             communityId: this.communityId, | ||||
|             areaId: this.areaId, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|     }, | ||||
|  | ||||
|     // 添加 | ||||
|     onAdd(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'add', | ||||
|         params: { | ||||
|           id: id || '', | ||||
|           bulidId: this.id, | ||||
|           communityId: this.communityId, | ||||
|         }, | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 房屋信息 | ||||
|     toBuildMsg(row) { | ||||
|       this.$emit('change', { | ||||
|         type: 'buildmsg', | ||||
|         params: { | ||||
|           ...row, | ||||
|         }, | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 删除 | ||||
|     remove(id) { | ||||
|       this.$confirm('确定删除该数据?').then(() => { | ||||
|         this.instance.post(`/app/appcommunitybuildinginfo/delete?ids=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('删除成功!') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     removeAll() { | ||||
|       var id = this.ids.join(',') | ||||
|       this.remove(id) | ||||
|     }, | ||||
|  | ||||
|     handleTreeFilter(v, data) { | ||||
|       return data?.name.indexOf(v) > -1 | ||||
|     }, | ||||
|  | ||||
|     handleSelectGrid(data) { | ||||
|       this.isAdd = false | ||||
|       if (data.type == 1) { | ||||
|         this.isAdd = true | ||||
|         this.communityId = data.id | ||||
|         this.areaId = null | ||||
|       } else if (data.type == 0) { | ||||
|         this.communityId = null | ||||
|         this.areaId = data.id | ||||
|       } | ||||
|       this.getList() | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppPetitionManage { | ||||
|   height: 100%; | ||||
|  | ||||
|   .ai-detail { | ||||
|     ::v-deep .ai-detail__content { | ||||
|       .ai-detail__content--wrapper { | ||||
|         display: flex; | ||||
|         justify-content: space-between; | ||||
|         height: 100%; | ||||
|         max-width: 100%; | ||||
|         padding: 15px; | ||||
|  | ||||
|         .AiTreeMenu { | ||||
|           width: 22%; | ||||
|         } | ||||
|  | ||||
|         .flex { | ||||
|           width: 78%; | ||||
|           margin-left: 10px; | ||||
|           padding: 15px; | ||||
|           background-color: #fff; | ||||
|  | ||||
|           .ai-search-ba { | ||||
|             margin-top: 10px; | ||||
|           } | ||||
|  | ||||
|           .ai-table { | ||||
|             margin-top: 0 !important; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-tree { | ||||
|     .el-tree-node__content { | ||||
|       display: inline-flex; | ||||
|       min-width: 100%; | ||||
|  | ||||
|       &:hover { | ||||
|         background: #e8efff; | ||||
|         color: #222222; | ||||
|         border-radius: 2px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .is-current > .el-tree-node__content { | ||||
|       background: #2266ff; | ||||
|  | ||||
|       &:hover { | ||||
|         background: #2266ff; | ||||
|         color: #fff; | ||||
|       } | ||||
|  | ||||
|       span { | ||||
|         color: #fff; | ||||
|         font-weight: bold; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										1252
									
								
								packages/2.0.5/AppBuildMap/AppBuildMap.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1252
									
								
								packages/2.0.5/AppBuildMap/AppBuildMap.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										443
									
								
								packages/2.0.5/AppBuildMap/buildingStatistics.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								packages/2.0.5/AppBuildMap/buildingStatistics.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,443 @@ | ||||
| <template> | ||||
|   <section class="buildingStatistics"> | ||||
|     <ai-title v-if="!isFormDv" title="楼栋统计" isShowBack isShowBottomBorder @onBackClick="$router.push({query:{}}),$parent.info={},$parent.isShowInfo=false,$parent.house=null,$parent.chooseBuildId=''"/> | ||||
|     <div class="buildingPane"> | ||||
|       <div class="bgItem tree"/> | ||||
|         <div class="building"> | ||||
|           <template v-if="floorRooms.length>0"> | ||||
|             <div class="buildingSignboard">{{ `${currentBuilding.buildingNumber}栋 ${unitNumber}单元` }} | ||||
|             </div> | ||||
|             <el-scrollbar class="floors"> | ||||
|               <div class="floor" v-for="(fl,j) in floorRooms" :key="j"> | ||||
|                 <div class="room" v-for="(op,i) in fl" :key="op.id" @click="handleSelectRoom(op,$event)" @touchstart="handleSelectRoom(op,$event)" :class="[{none:op.livingNumber==0,selected:selected.houseCode==op.houseCode},handleTipsHighlight(op.tips)]"> | ||||
|                   {{ op.houseCode }} | ||||
|                   <div v-if="op.livingNumber==0">无人</div> | ||||
|                   <div v-show="op.id==selected.id" class="detail" @click.stop :style="{left:position.x,top:position.y}"> | ||||
|                     <el-row class="popupHeader" type="flex" justify="space-between" align="middle"> | ||||
|                       <span>{{selected.houseCode}}详情</span> | ||||
|                       <ai-icon icon="iconClean" @click.native.stop="selected={}"/> | ||||
|                     </el-row> | ||||
|                     <div class="family-member"> | ||||
|                       <h2>房主信息</h2> | ||||
|                       <div v-for="(item,index) in selected.owner" :key="item.id"> | ||||
|                         <div class="family-member__item"> | ||||
|                           <div class="member-left"> | ||||
|                             <label>{{item.name}}</label> | ||||
|                           </div> | ||||
|                           <span style="color: #2266FF">{{root.dict.getLabel("houseLivingType",item.livingType)}}</span> | ||||
|                         </div> | ||||
|                         <div class="family-member__item"> | ||||
|                           <div class="member-left"> | ||||
|                             <label>联系方式</label> | ||||
|                           </div> | ||||
|                           <span style="color: #2266FF;">{{item.phone}}</span> | ||||
|                         </div> | ||||
|                       </div> | ||||
|  | ||||
|                       <h2>承租人信息</h2> | ||||
|                       <div v-for="(item,index) in selected.renter" :key="item.id"> | ||||
|                         <div class="family-member__item" > | ||||
|                           <div class="member-left"> | ||||
|                             <label>{{item.name}}</label> | ||||
|                           </div> | ||||
|                           <span style="color: #2266FF">{{root.dict.getLabel("houseLivingType",item.livingType)}}</span> | ||||
|                         </div> | ||||
|                         <div class="family-member__item"> | ||||
|                           <div class="member-left"> | ||||
|                             <label>联系方式</label> | ||||
|                           </div> | ||||
|                           <span>{{item.phone}}</span> | ||||
|                         </div> | ||||
|                       </div> | ||||
|  | ||||
|                       <h2>实际居住人员</h2> | ||||
|                       <div v-for="(item,index) in selected.live" :key="item.id"> | ||||
|                         <div class="family-member__item"> | ||||
|                           <div class="member-left"> | ||||
|                             <label>{{item.name}}</label> | ||||
|                           </div> | ||||
|                           <span>{{root.dict.getLabel("householdRelation",item.relation)}}</span> | ||||
|                         </div> | ||||
|                       </div> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </el-scrollbar> | ||||
|           </template> | ||||
|           <ai-empty v-else>请在【<b>小区总览</b>】中选取【楼栋单元】</ai-empty> | ||||
|           <div class="bottom"/> | ||||
|         </div> | ||||
|       <building-tool-bar></building-tool-bar> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import BuildingToolBar from "./buildingToolBar"; | ||||
|  | ||||
| export default { | ||||
|   name: "buildingStatistics", | ||||
|   components: {BuildingToolBar}, | ||||
|   inject: ['root'], | ||||
|   provide() { | ||||
|     return { | ||||
|       sta: this | ||||
|     } | ||||
|   }, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     isFormDv: Boolean, | ||||
|     query: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       rooms: [], | ||||
|       selected: {}, | ||||
|       currentBuilding: {}, | ||||
|       unitNumber:1, | ||||
|       tips: [], | ||||
|       position:{ | ||||
|         x:"", | ||||
|         y:"" | ||||
|       }, | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     floorRooms() { | ||||
|       let obj = {} | ||||
|       this.rooms.map(e => { | ||||
|         e.none = e.isNone == 0 | ||||
|         return obj[e.layerNumber]?.push(e) || (obj[e.layerNumber] = [e]) | ||||
|       }) | ||||
|       return Object.values(obj).reverse() | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load('householdRelation', 'residentTipType',"houseLivingType") | ||||
|     if (this.isFormDv && this.query.buildingId) { | ||||
|       this.getRoomsByBuilding(this.query.buildingId, this.query.unitNum) | ||||
|       this.currentBuilding = { buildingNumber: this.query.buildingNumber} | ||||
|       this.unitNumber = this.query.unitNum | ||||
|  | ||||
|       return false | ||||
|     } | ||||
|     this.getRoomsByBuilding(this.$route.query?.buildingId,this.$route.query?.unitNum) | ||||
|     this.currentBuilding = {buildingNumber: this.$route.query?.buildingNumber}; | ||||
|     this.unitNumber = this.$route.query?.unitNum; | ||||
|   }, | ||||
|   methods: { | ||||
|     handleSelectRoom(room, e) { | ||||
|       console.log(e) | ||||
|       if (room.livingNumber>0) { | ||||
|         this.$nextTick(()=>{ | ||||
|           this.position.x = e.pageX + 40 + "px" | ||||
|           this.position.y = e.pageY + "px" | ||||
|           this.selected = room; | ||||
|           this.$forceUpdate() | ||||
|         }) | ||||
|         // this.getRoomDetail(room.id) | ||||
|       } | ||||
|     }, | ||||
|     selectedBuilding(building,unitNumber) { | ||||
|       this.selected = {} | ||||
|       this.tips = [] | ||||
|       this.$router.push({query: {...this.$route.query, buildingId: building.id,unitNum:unitNumber}}).catch(e=>{e}) | ||||
|       this.currentBuilding = building | ||||
|       this.unitNumber = unitNumber | ||||
|       this.getRoomsByBuilding(building.id,unitNumber) | ||||
|     }, | ||||
|     getRoomsByBuilding(buildingId,unitNumber) { | ||||
|       this.root.instance.post("/app/appcommunityhouseinfo/list", null, { | ||||
|         params: { | ||||
|           unitNumber, | ||||
|           buildingId, | ||||
|           size: 999 | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.rooms = res.data.records | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getRoomDetail(id) { | ||||
|       return this.root.instance.post("/app/appcommunityhouseinfo/queryDetailById", null, { | ||||
|         params: {id} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           let {residents} = res.data | ||||
|           this.selected = { | ||||
|             ...this.selected, ...res.data, | ||||
|             residents: residents.map(e => { | ||||
|               let {tips} = e | ||||
|               //显示为户主 | ||||
|               let relationLabel = e.householdName == 1 ? "户主" : this.root.dict.getLabel("householdRelation", e.householdRelation) | ||||
|               return {...e, tips: tips ? tips.split("|") : [], relationLabel} | ||||
|             } | ||||
|             ) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleTipsHighlight(tip) { | ||||
|       let flag = this.tips.length > 0 && !this.tips.some(t => tip?.split("|").includes(t)) | ||||
|       return flag ? 'tipsHighlight' : '' | ||||
|     }, | ||||
|     selectedTips(tips) { | ||||
|       this.tips = tips | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .buildingStatistics { | ||||
|   height: 100%; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|  | ||||
|   ::v-deep .ailist-title{ | ||||
|     margin: 0 20px; | ||||
|   } | ||||
|  | ||||
|   .family-member { | ||||
|     & > h2 { | ||||
|       height: 32px; | ||||
|       line-height: 32px; | ||||
|       margin: 0; | ||||
|       padding: 0 12px; | ||||
|       color: #333333; | ||||
|       font-size: 12px; | ||||
|       font-weight: 700; | ||||
|       text-align: left; | ||||
|       background: #E3E8F1; | ||||
|     } | ||||
|  | ||||
|     .family-member__item { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
|       height: 32px; | ||||
|       padding: 0 12px; | ||||
|       background: #F3F6F9; | ||||
|  | ||||
|       .member-left { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         gap: 4px; | ||||
|       } | ||||
|  | ||||
|       &:nth-of-type(2n) { | ||||
|         background: #fff; | ||||
|       } | ||||
|  | ||||
|       label { | ||||
|         font-weight: normal !important; | ||||
|         color: #333; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|  | ||||
|       & > span { | ||||
|         color: #666666; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     &:last-child { | ||||
|       label { | ||||
|         color: #666666; | ||||
|         font-weight: normal !important; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .buildingPane { | ||||
|     background-image: url("https://cdn.cunwuyun.cn/buildSta/cloud.png"), linear-gradient(3deg, #FFFFFF 0%, #3093FF 100%); | ||||
|     background-repeat: no-repeat; | ||||
|     background-position: 227px 43px, 100%; | ||||
|     background-size: 788px 112px, 100%; | ||||
|     position: relative; | ||||
|     box-sizing: border-box; | ||||
|     padding-right: 400px; | ||||
|     flex: 1; | ||||
|     min-height: 0; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     justify-content: flex-end; | ||||
|     align-items: flex-start; | ||||
|  | ||||
|     .bgItem { | ||||
|       position: absolute; | ||||
|       background-repeat: no-repeat; | ||||
|       pointer-events: none; | ||||
|  | ||||
|       &.tree { | ||||
|         left: calc(50% - 200px); | ||||
|         transform: translateX(-50%); | ||||
|         bottom: 0; | ||||
|         width: 580px; | ||||
|         height: 71px; | ||||
|         background-image: url("https://cdn.cunwuyun.cn/buildSta/tree.png"); | ||||
|         z-index: 3; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .building { | ||||
|       margin-left: 60px; | ||||
|       flex-shrink: 0; | ||||
|       height: auto; | ||||
|       width: auto; | ||||
|       box-sizing: border-box; | ||||
|       padding: 136px 0 0; | ||||
|       background-image: url("https://cdn.cunwuyun.cn/buildSta/roof.png"), | ||||
|       url("https://cdn.cunwuyun.cn/buildSta/chimney.png"); | ||||
|       background-position: 0 121px, 70px 91px; | ||||
|       background-size: 100% 105px, 70px; | ||||
|       background-repeat: no-repeat; | ||||
|       display: flex; | ||||
|       flex-direction: column; | ||||
|       justify-content: flex-end; | ||||
|       align-items: center; | ||||
|       border-bottom: 10px solid #E9C28E; | ||||
|  | ||||
|       .buildingSignboard { | ||||
|         padding-top: 41px; | ||||
|         width: 200px; | ||||
|         height: 65px; | ||||
|         text-align: center; | ||||
|         background-image: url("https://cdn.cunwuyun.cn/buildSta/buildingSignboard.png"); | ||||
|         background-repeat: no-repeat; | ||||
|         box-sizing: border-box; | ||||
|         font-size: 12px; | ||||
|         font-weight: bold; | ||||
|         color: #1D3296; | ||||
|         margin-bottom: 15px; | ||||
|       } | ||||
|  | ||||
|       .ai-empty { | ||||
|         background: #FFECD9; | ||||
|         margin: 90px 20px 0; | ||||
|         padding: 0 10px 90px; | ||||
|         font-size: 14px; | ||||
|         color: #666; | ||||
|  | ||||
|         b { | ||||
|           color: #26f | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .bottom { | ||||
|         background: #FFECD9; | ||||
|         height: 50px; | ||||
|         width: calc(100% - 40px); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     ::v-deep .floors { | ||||
|       max-height: 520px; | ||||
|  | ||||
|       .el-scrollbar__wrap { | ||||
|         overflow-x: hidden; | ||||
|         margin-bottom: 0 !important; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .floor { | ||||
|       margin: 0 20px; | ||||
|       height: 105px; | ||||
|       flex-shrink: 0; | ||||
|       max-width: calc(100% - 40px); | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       background-image: url("https://cdn.cunwuyun.cn/buildSta/floor.png"); | ||||
|       background-size: 100% 105px; | ||||
|       padding: 0 30px; | ||||
|       box-sizing: border-box; | ||||
|       gap: 20px; | ||||
|  | ||||
|       .room { | ||||
|         width: 60px; | ||||
|         height: 72px; | ||||
|         background-image: url("https://cdn.cunwuyun.cn/buildSta/room.png"); | ||||
|         text-align: center; | ||||
|         padding-top: 20px; | ||||
|         box-sizing: border-box; | ||||
|         font-size: 14px; | ||||
|         font-weight: bold; | ||||
|         color: #FFFFFF; | ||||
|         cursor: pointer; | ||||
|         position: relative; | ||||
|  | ||||
|         .detail { | ||||
|           position: fixed; | ||||
|           width: 320px; | ||||
|           background: #fff; | ||||
|           box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1); | ||||
|           border-radius: 4px; | ||||
|           overflow: hidden; | ||||
|           display: flex; | ||||
|           flex-direction: column; | ||||
|           z-index: 11; | ||||
|           transform: translateY(-100%); | ||||
|  | ||||
|           .popupHeader { | ||||
|             background: #D42222; | ||||
|             padding: 0 12px; | ||||
|             height: 32px; | ||||
|  | ||||
|             .AiIcon { | ||||
|               width: 16px; | ||||
|               height: 16px; | ||||
|             } | ||||
|           } | ||||
|  | ||||
|           li { | ||||
|             list-style-type: none; | ||||
|             display: flex; | ||||
|             justify-content: space-between; | ||||
|             align-items: center; | ||||
|             padding: 0 12px; | ||||
|             font-size: 12px; | ||||
|             color: #333; | ||||
|             height: 32px; | ||||
|  | ||||
|             & > div { | ||||
|  | ||||
|             } | ||||
|  | ||||
|             &.title { | ||||
|               background: #E3E8F1; | ||||
|             } | ||||
|  | ||||
|             &.stretch { | ||||
|               background: #F3F6F9; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         &.none { | ||||
|           cursor: not-allowed; | ||||
|           color: #f46; | ||||
|           background-image: url("https://cdn.cunwuyun.cn/buildSta/roomNone.png"); | ||||
|         } | ||||
|  | ||||
|         &.selected { | ||||
|           background-image: url("https://cdn.cunwuyun.cn/buildSta/roomSelected.png"); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .buildingToolBar { | ||||
|       position: absolute; | ||||
|       right: 20px; | ||||
|       top: 20px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .tipsHighlight { | ||||
|     opacity: 0.6; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										95
									
								
								packages/2.0.5/AppBuildMap/buildingToolBar.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								packages/2.0.5/AppBuildMap/buildingToolBar.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| <template> | ||||
|   <section class="buildingToolBar"> | ||||
|     <div class="toolBar"> | ||||
|       <div class="nav" v-for="(op,i) in navs" :key="i" :class="{selected:i==active}" @click="active=i"> | ||||
|         <ai-icon :icon="op.icon"/> | ||||
|         <div>{{ op.name }}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <component :is="currentNav.comp" class="toolPane"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import BuildingInfo from "./toolBar/buildingInfo"; | ||||
| import CommunityOverview from "./toolBar/communityOverview"; | ||||
| // import NearbyGCS from "./toolBar/nearbyGCS"; | ||||
| import RecentEvents from "./toolBar/recentEvents"; | ||||
|  | ||||
| export default { | ||||
|   name: "buildingToolBar", | ||||
|   components: {RecentEvents, CommunityOverview, BuildingInfo}, | ||||
|   computed: { | ||||
|     navs() { | ||||
|       return [ | ||||
|         {icon: 'icondanweiguanli', name: "单元统计", comp: BuildingInfo}, | ||||
|         {icon: 'icondanweiguanli', name: "单元切换", comp: CommunityOverview}, | ||||
|         // {icon: 'icondanweiguanli', name: "网格员", comp: NearbyGCS}, | ||||
|         // {icon: 'icondanweiguanli', name: "近期事件", comp: RecentEvents}, | ||||
|       ] | ||||
|     }, | ||||
|     currentNav() { | ||||
|       return this.navs[this.active] | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       active: 0 | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .buildingToolBar { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   gap: 10px; | ||||
|  | ||||
|   .toolBar { | ||||
|     height: 40px; | ||||
|     background: #FFFFFF; | ||||
|     box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2); | ||||
|     border-radius: 4px; | ||||
|     padding: 4px; | ||||
|     width: 400px; | ||||
|     display: flex; | ||||
|     gap: 8px; | ||||
|     box-sizing: border-box; | ||||
|     align-self: flex-end; | ||||
|  | ||||
|     .nav { | ||||
|       flex: 1; | ||||
|       height: 32px; | ||||
|       color: #3A3A3A; | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: center; | ||||
|       font-size: 12px; | ||||
|       cursor: pointer; | ||||
|  | ||||
|       .AiIcon { | ||||
|         width: 16px; | ||||
|         height: 16px; | ||||
|         margin-right: 4px; | ||||
|       } | ||||
|  | ||||
|       &:hover { | ||||
|         color: #2266FF; | ||||
|       } | ||||
|  | ||||
|       &.selected { | ||||
|         background: #E4F0FF; | ||||
|         color: #2266FF; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .toolPane { | ||||
|     background: #FFFFFF; | ||||
|     box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1); | ||||
|     border-radius: 4px; | ||||
|     overflow: hidden; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										249
									
								
								packages/2.0.5/AppBuildMap/toolBar/buildingInfo.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								packages/2.0.5/AppBuildMap/toolBar/buildingInfo.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | ||||
| <template> | ||||
|   <section class="buildingInfo"> | ||||
|     <ai-title title="人口信息"/> | ||||
|     <div class="infoPane"> | ||||
|       <div class="staZone"> | ||||
|         <div v-for="(value, name) in staData" :key="name"> | ||||
|           <b>{{ value }}</b> | ||||
|           <span>{{ name }}</span> | ||||
|         </div> | ||||
|       </div> | ||||
| <!--      <div id="PersonStaChart"/>--> | ||||
|       <div class="static-wrap"> | ||||
|         <div class="sta-item" v-for="(value,name) in tag" :key="name"> | ||||
|           <div class="sta-left"> | ||||
|             <em class="tag" :style="{backgroundColor:color[name]}"></em> | ||||
|             <label>{{name}}</label> | ||||
|           </div> | ||||
|           <span class="num">{{value}}</span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <ai-title title="房屋信息"/> | ||||
|     <div class="infoPane"> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>所属社区</span> | ||||
|         <span>{{build.areaName}}</span> | ||||
|       </el-row> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>所属小区</span> | ||||
|         <span>{{build.communityName}}</span> | ||||
|       </el-row> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>房屋类型</span> | ||||
|         <span>{{root.dict.getLabel("communityBuildingType",build.buildingType)}}</span> | ||||
|       </el-row> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>楼长姓名</span> | ||||
|         <span>{{build.managerName}}</span> | ||||
|       </el-row> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>联系方式</span> | ||||
|         <span>{{build.managerPhone}}</span> | ||||
|       </el-row> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import * as echarts from 'echarts' | ||||
|  | ||||
| export default { | ||||
|   name: "buildingInfo", | ||||
|   inject: ['root', 'sta'], | ||||
|   computed: { | ||||
|     chartData() { | ||||
|       return this.root.dict.getDict("residentTipType").map(e => ({ | ||||
|         name: e.dictName, | ||||
|         key: e.dictValue, | ||||
|         color: e.dictColor, | ||||
|         v1: 0 | ||||
|       })) | ||||
|     }, | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {prop:"areaName",label:"所属社区"} | ||||
|       ]; | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       chart: null, | ||||
|       staData: {}, | ||||
|       tag:{}, | ||||
|       color:{}, | ||||
|       build:{}, | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     initChart(data) { | ||||
|       this.chart = echarts.init(document.getElementById("PersonStaChart")) | ||||
|       let selected = {}, color = [] | ||||
|       this.chartData.map(e => { | ||||
|         selected[e.name] = false | ||||
|         color.push(e.color) | ||||
|       }) | ||||
|       this.chart.setOption({ | ||||
|         grid: {top: 31, right: 0, height: 135}, | ||||
|         tooltip: {}, | ||||
|         legend: { | ||||
|           top: 185, | ||||
|           left: 0, | ||||
|           orient: "vertical", | ||||
|           selected, | ||||
|           itemWidth: 14, | ||||
|           itemHeight: 14, | ||||
|           itemGap: 12, | ||||
|           icon: "rect", | ||||
|           formatter: name => { | ||||
|             let item = data.find(e => this.root.dict.getLabel('residentTipType', e.name) == name) | ||||
|             return `{a|${name}}  {b|${item.v1}}` | ||||
|           }, | ||||
|           textStyle: { | ||||
|             rich: { | ||||
|               a: {color: "#666", width: 123}, | ||||
|               b: {color: "#333", fontWeight: 'bold', align: 'right'} | ||||
|             } | ||||
|           } | ||||
|         }, color, | ||||
|         yAxis: {type: 'value', min: 0, minInterval: 1, axisTick: false, axisLine: false, axisLabel: {color: "#666"}}, | ||||
|         xAxis: {type: 'category', axisTick: false, axisLine: false, axisLabel: false}, | ||||
|         series: data.map(e => ({ | ||||
|           type: 'bar', | ||||
|           barWidth: 8, | ||||
|           barGap: '250%', | ||||
|           name: this.root.dict.getLabel('residentTipType', e.name) | ||||
|         })) | ||||
|       }) | ||||
|       this.chart.on('legendselectchanged', ({selected}) => { | ||||
|         let tips = Object.keys(selected)?.filter(e => selected[e])?.map(e => this.root.dict.getValue('residentTipType', e)) | ||||
|         this.sta?.selectedTips(tips) | ||||
|       }) | ||||
|       this.getChartData(data) | ||||
|     }, | ||||
|     getChartData(data) { | ||||
|       this.chart?.setOption({ | ||||
|         series: data.map(e => ({data: [e.v1]})) | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   created(){ | ||||
|     this.root.dict?.load("communityBuildingType") | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.root.instance.post("/app/appcommunitybuildinginfo/statistics", null, { | ||||
|       params: { | ||||
|         id: this.root.isFormDv ? this.root.info.id : this.$route.query.buildingId, | ||||
|         unitNum: this.root.isFormDv ? this.root.info.unitNumber : this.$route.query.unitNum, | ||||
|       } | ||||
|     }).then(res => { | ||||
|       if (res?.data) { | ||||
|         this.staData = res.data.unit; | ||||
|         this.tag = res.data.tag; | ||||
|         this.color = res.data.color; | ||||
|         this.build = res.data.build; | ||||
|         // this.root.dict.load('residentTipType').then(() => { | ||||
|         //   this.initChart(res.data.lx) | ||||
|         // }) | ||||
|       } | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .buildingInfo { | ||||
|   ::v-deep .infoPane { | ||||
|     box-sizing: border-box; | ||||
|     padding: 10px 20px; | ||||
|  | ||||
|     .info-item{ | ||||
|       height: 32px; | ||||
|       box-sizing: border-box; | ||||
|       padding: 0 12px; | ||||
|       font-size: 12px; | ||||
|       color: #666666; | ||||
|       align-items: center; | ||||
|  | ||||
|       span:last-child{ | ||||
|         color: #333333; | ||||
|       } | ||||
|  | ||||
|       &:nth-child(2n-1){ | ||||
|         background-color: #F3F6F9; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .static-wrap{ | ||||
|       width: 360px; | ||||
|       box-sizing: border-box; | ||||
|       padding-top: 20px; | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
|       flex-wrap: wrap; | ||||
|  | ||||
|       .sta-item{ | ||||
|         width: 46%; | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         justify-content: space-between; | ||||
|         margin-bottom: 8px; | ||||
|  | ||||
|         .sta-left{ | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           .tag{ | ||||
|             width: 14px; | ||||
|             height: 14px; | ||||
|             background: #DC1739; | ||||
|             border-radius: 2px; | ||||
|             margin-right: 3px; | ||||
|           } | ||||
|           & > label{ | ||||
|             font-size: 12px; | ||||
|             color: #666666; | ||||
|           } | ||||
|         } | ||||
|         .num{ | ||||
|           font-size: 12px; | ||||
|           color: #333333; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     .staZone { | ||||
|       height: 80px; | ||||
|       background: #F5F7F9; | ||||
|       border-radius: 4px; | ||||
|       overflow: hidden; | ||||
|       display: flex; | ||||
|  | ||||
|       & > div { | ||||
|         flex: 1; | ||||
|         min-width: 0; | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         justify-content: center; | ||||
|         align-items: center; | ||||
|         height: 100%; | ||||
|         font-size: 12px; | ||||
|         color: #333; | ||||
|  | ||||
|         b { | ||||
|           font-size: 24px; | ||||
|           font-family: DINAlternate-Bold, DINAlternate,serif; | ||||
|           color: #2266FF; | ||||
|           margin-bottom: 4px; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     #PersonStaChart { | ||||
|       width: 100%; | ||||
|       height: 350px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										116
									
								
								packages/2.0.5/AppBuildMap/toolBar/communityOverview.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								packages/2.0.5/AppBuildMap/toolBar/communityOverview.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| <template> | ||||
|   <section class="communityOverview"> | ||||
|     <ai-title title="小区总览"/> | ||||
|     <div class="units" v-if="Object.keys(buildingUnits).length>0"> | ||||
|       <div class="building" v-for="(value,name) in buildingUnits" :key="name"> | ||||
|         <div class="unit" v-for="(op,j) in value" :key="j" @click="sta.selectedBuilding(op,j+1)" | ||||
|              :class="{selected:sta.unitNumber==j+1 && sta.currentBuilding.buildingNumber==name}"> | ||||
|           <b>{{ name}}栋</b> | ||||
|           <div>{{ j+1 }}单元</div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <AiEmpty v-else>暂无楼栋信息,请进入【楼栋管理】添加</AiEmpty> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "communityOverview", | ||||
|   inject: ['root', 'sta'], | ||||
|   computed: { | ||||
|     buildingUnits() { | ||||
|       let obj = {} | ||||
|       this.units.map(e => { | ||||
|         for(let i=0;i<e.unitNumber;i++){ | ||||
|           obj[e.buildingNumber]?.push(e) || (obj[e.buildingNumber] = [e]) | ||||
|         } | ||||
|       }) | ||||
|       return obj; | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       units: [] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getUnits(communityId) { | ||||
|       this.root.instance.post("/app/appcommunitybuildinginfo/list", null, { | ||||
|         params: { | ||||
|           communityId, | ||||
|           size: 999 | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.units = res.data.records | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getUnits(this.root.isFormDv ? this.root.info.communityId : this.$route.query.communityId) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .communityOverview { | ||||
|   max-width: 400px; | ||||
|  | ||||
|   .units { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|     padding: 0 20px 20px; | ||||
|     align-items: flex-start; | ||||
|  | ||||
|     .building { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       height: auto; | ||||
|       flex-wrap: wrap;  | ||||
|  | ||||
|       .unit { | ||||
|         margin-right: 10px; | ||||
|         margin-bottom: 10px; | ||||
|  | ||||
|         &:nth-of-type(5) { | ||||
|           margin-right: 0; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .unit { | ||||
|       width: 64px; | ||||
|       height: 56px; | ||||
|       background: #F8FBFF; | ||||
|       border-radius: 2px 0 0 2px; | ||||
|       border: 1px solid #829CCF; | ||||
|       display: flex; | ||||
|       flex-direction: column; | ||||
|       justify-content: center; | ||||
|       align-items: center; | ||||
|       font-size: 12px; | ||||
|       color: #999; | ||||
|       cursor: pointer; | ||||
|  | ||||
|       b { | ||||
|         color: #424242; | ||||
|       } | ||||
|  | ||||
|       &.selected { | ||||
|         color: #fff; | ||||
|         background: #2266FF; | ||||
|  | ||||
|         b { | ||||
|           color: #fff; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .ai-empty { | ||||
|     height: 240px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										129
									
								
								packages/2.0.5/AppBuildMap/toolBar/nearbyGCS.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								packages/2.0.5/AppBuildMap/toolBar/nearbyGCS.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| <template> | ||||
|   <section class="nearbyGCS"> | ||||
|     <ai-title title="全部网格员"/> | ||||
|     <div class="radarPane"> | ||||
|       <div class="radar"> | ||||
|         <div class="indicator"/> | ||||
|       </div> | ||||
|       <div class="gcsItem" v-for="(op,i) in userList" :key="i" :style="op.style"> | ||||
|         <i class="dot" :class="{offline:op.offline}"/> | ||||
|         <span>{{ op.name }}</span> | ||||
|         <ai-icon icon="iconIM"/> | ||||
|       </div> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "nearbyGCS", | ||||
|   inject: ['root', 'sta'], | ||||
|  | ||||
|   data () { | ||||
|     return { | ||||
|       userList: [] | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   mounted () { | ||||
|     this.getInfo() | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getInfo () { | ||||
|       this.root.instance.post('/app/appgirdmemberinfo/queryGirdMemberByBuilding', null, { | ||||
|         params: {buildingId: this.$route.query.buildingId} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.gcsList(res.data) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     gcsList (data) { | ||||
|       this.userList = data.map(e => ({ | ||||
|         ...e, | ||||
|         style: { | ||||
|           transform: `translate( | ||||
|         ${Math.round(160 * (Math.random() - 0.5))}px, | ||||
|         ${Math.round(160 * (Math.random() - 0.5))}px)`} | ||||
|       })) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .nearbyGCS { | ||||
|   .radarPane { | ||||
|     width: 100%; | ||||
|     height: 360px; | ||||
|     display: flex; | ||||
|     justify-content: center; | ||||
|     align-items: center; | ||||
|     position: relative; | ||||
|  | ||||
|     .gcsItem { | ||||
|       position: absolute; | ||||
|       width: 92px; | ||||
|       height: 28px; | ||||
|       background: #FFFFFF; | ||||
|       box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); | ||||
|       border-radius: 16px; | ||||
|       font-size: 12px; | ||||
|       color: #333333; | ||||
|       display: flex; | ||||
|       justify-content: center; | ||||
|       align-items: center; | ||||
|       z-index: 3; | ||||
|       gap: 8px; | ||||
|  | ||||
|       .AiIcon { | ||||
|         width: 16px; | ||||
|         height: 16px; | ||||
|       } | ||||
|  | ||||
|       .dot { | ||||
|         width: 4px; | ||||
|         height: 4px; | ||||
|         background: #30BC77; | ||||
|  | ||||
|         &.offline { | ||||
|           background: #FF4466; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .radar { | ||||
|     width: 320px; | ||||
|     height: 320px; | ||||
|     position: relative; | ||||
|     border-radius: 50%; | ||||
|     overflow: hidden; | ||||
|     background-image: url("https://cdn.cunwuyun.cn/buildSta/radarBg.png"); | ||||
|  | ||||
|     .indicator { | ||||
|       position: absolute; | ||||
|       width: 160px; | ||||
|       height: 160px; | ||||
|       top: 0; | ||||
|       left: 0; | ||||
|       transform-origin: 100% 100%; | ||||
|       background: linear-gradient(190deg, rgba(162, 255, 182, 0.5) 0%, rgba(162, 255, 215, 0) 100%); | ||||
|       border-right: 1px solid #A2FFB6; | ||||
|       animation: radar 5s linear infinite; | ||||
|       z-index: 2; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @keyframes radar { | ||||
|   0% { | ||||
|     transform: rotate(0deg) | ||||
|   } | ||||
|   100% { | ||||
|     transform: rotate(360deg) | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										81
									
								
								packages/2.0.5/AppBuildMap/toolBar/recentEvents.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								packages/2.0.5/AppBuildMap/toolBar/recentEvents.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| <template> | ||||
|   <section class="recentEvents"> | ||||
|     <ai-title title="楼栋近期相关事件"/> | ||||
|     <div class="recentEvents-list"> | ||||
|       <div class="recentEvents-item" v-for="(item, index) in 4" :key="index"> | ||||
|         <div class="recentEvents-item__top"> | ||||
|           <i>[已解决]</i> | ||||
|           <span>102室与402室矛盾纠纷</span> | ||||
|         </div> | ||||
|         <div class="recentEvents-item__middle"> | ||||
|           <span>102室与402室矛盾纠纷</span> | ||||
|           <em>[张三]</em> | ||||
|           <span>接到了</span> | ||||
|           <em>[矛盾调解]</em> | ||||
|           <span>任务,事件目前</span> | ||||
|           <i>[已完成]</i> | ||||
|         </div> | ||||
|         <div class="recentEvent-item__bottom">2019-06-18 13:35:45</div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "recentEvents" | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .recentEvents { | ||||
|   font-size: 14px; | ||||
|   width: 100%; | ||||
|  | ||||
|   .recentEvents-list { | ||||
|     .recentEvents-item { | ||||
|       border-bottom: 1px solid #E6E8EE; | ||||
|       background: transparent; | ||||
|       padding: 10px; | ||||
|       box-sizing: border-box; | ||||
|       .recentEvent-item__bottom { | ||||
|         color: #999; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|  | ||||
|       &:first-child { | ||||
|         background: #EFF6FF; | ||||
|         border-bottom: none; | ||||
|       } | ||||
|  | ||||
|       &:last-child { | ||||
|         border-bottom: none; | ||||
|       } | ||||
|  | ||||
|       .recentEvents-item__top { | ||||
|         display: flex; | ||||
|       } | ||||
|  | ||||
|       .recentEvents-item__middle { | ||||
|         margin: 6px 0 10px; | ||||
|       } | ||||
|  | ||||
|       span { | ||||
|         color: #666666; | ||||
|       } | ||||
|  | ||||
|       em { | ||||
|         color: #2266FF; | ||||
|         font-style: normal; | ||||
|       } | ||||
|  | ||||
|       i { | ||||
|         font-style: normal; | ||||
|         color: #2EA222; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										71
									
								
								packages/2.0.5/AppCodeGeneration/AppCodeGeneration.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								packages/2.0.5/AppCodeGeneration/AppCodeGeneration.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| <template> | ||||
|   <component | ||||
|     v-if="hasApp && configLoaded" | ||||
|     :is="componentName" | ||||
|     :params="params" | ||||
|     :backType="backType" | ||||
|     :instance="instance" | ||||
|     :dict="dict" | ||||
|     :appType="appType" | ||||
|     :appId="appId" | ||||
|     :configs="configs" | ||||
|     @change="changePage" /> | ||||
|   <ai-empty v-else-if="hasApp">应用配置加载中...</ai-empty> | ||||
|   <ai-empty v-else>读取应用失败</ai-empty> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import Add from './components/Add.vue' | ||||
|   import Detail from './components/Detail.vue' | ||||
|   import List from './components/List.vue' | ||||
|  | ||||
|   export default { | ||||
|     label: '代码生成', | ||||
|     name: 'AppCodeGeneration', | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|     components: {Add, Detail, List}, | ||||
|     computed: { | ||||
|       appId() { | ||||
|         return this.$route.query.app | ||||
|       }, | ||||
|       hasApp() { | ||||
|         return !!this.appId | ||||
|       }, | ||||
|       configLoaded() { | ||||
|         return !!this.configs.id | ||||
|       } | ||||
|     }, | ||||
|     data() { | ||||
|       return { | ||||
|         componentName: 'list', | ||||
|         params: {}, | ||||
|         backType: '', | ||||
|         configs: {}, | ||||
|         appType: '' | ||||
|       } | ||||
|     }, | ||||
|     methods: { | ||||
|       changePage(data) { | ||||
|         this.componentName = data.type | ||||
|         this.params = data.params | ||||
|         this.backType = data.backType || '' | ||||
|       }, | ||||
|       getConfigs() { | ||||
|         this.instance.post(`/app/appapplicationinfo/queryApplicationInfo`, null, { | ||||
|           params: {appId: this.appId} | ||||
|         }).then((res) => { | ||||
|           if (res?.data) { | ||||
|             this.appType = res.data.appType | ||||
|             this.configs = res.data | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|     created() { | ||||
|       this.getConfigs() | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
							
								
								
									
										179
									
								
								packages/2.0.5/AppCodeGeneration/app/visit/Visit.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								packages/2.0.5/AppCodeGeneration/app/visit/Visit.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | ||||
| <template> | ||||
|   <ai-card title="走访记录" class="visit"> | ||||
|     <el-button slot="right" icon="iconfont iconAdd" type="text" @click="isShow = true">添加走访记录</el-button> | ||||
|     <template #content> | ||||
|       <div class="visit-list"> | ||||
|         <div class="visit-item" v-for="(item, index) in 10" :key="index"> | ||||
|           <div class="visit-item__top"> | ||||
|             <div class="left"> | ||||
|               <img src="https://p26-passport.byteacctimg.com/img/user-avatar/6401428bcd3b2b9bfed4f31cca07b798~300x300.image"> | ||||
|               <h2>且听风吟</h2> | ||||
|             </div> | ||||
|             <span>2020-07-05 12:02:33</span> | ||||
|           </div> | ||||
|           <p>且听风吟且听风吟且听风吟且听风吟且听风吟且听风吟且听风吟且听风吟且听风吟且听风吟且听风吟且听风吟</p> | ||||
|           <div class="visit-imgs"> | ||||
|           </div> | ||||
|           <div class="visit-status"> | ||||
|             <span>现实状态:</span> | ||||
|             <i>失联</i> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <ai-dialog | ||||
|         :visible.sync="isShow" | ||||
|         width="1000px" | ||||
|         height="500px" | ||||
|         title="数据源" | ||||
|         @close="onClose" | ||||
|         @onConfirm="onConfirm"> | ||||
|         <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|           <ai-bar title="基本信息">基本信息</ai-bar> | ||||
|           <div class="ai-form"> | ||||
|             <el-form-item label="走访人姓名" prop="description"> | ||||
|               <span>且听风吟</span> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="身份证账号" prop="description"> | ||||
|               <span>2131313</span> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="数据源描述" prop="description" :rules="[{ required: true, message: '请输入数据源描述', trigger: 'blur' }]"> | ||||
|               <el-input | ||||
|                 size="small" | ||||
|                 placeholder="请输入数据源描述" | ||||
|                 v-model="form.description"> | ||||
|               </el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="村微应用" prop="appId" :rules="[{ required: true, message: '请选择村微应用', trigger: 'change' }]"> | ||||
|               <el-select size="small" v-model="form.appId" placeholder="请选择村微应用"> | ||||
|                 <el-option | ||||
|                   v-for="item in appList" | ||||
|                   :key="item.id" | ||||
|                   :label="item.appName" | ||||
|                   :value="item.id"> | ||||
|                 </el-option> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-card> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'visit', | ||||
|  | ||||
|     props: ['id'], | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         appList: [], | ||||
|         isShow: false, | ||||
|         form: { | ||||
|           description: '', | ||||
|           appId: '' | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onConfirm () { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             this.instance.post(`/appdiylargescreen/addOrUpdateDatasource`, { | ||||
|               ...this.form, | ||||
|               id: this.id ? this.id : '' | ||||
|             }).then(res => { | ||||
|               if (res.code === 0) { | ||||
|                 this.$message.success(this.id ? '编辑成功' : '添加成功') | ||||
|                 this.isShow = false | ||||
|  | ||||
|                 this.getList() | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onClose () { | ||||
|  | ||||
|       }, | ||||
|  | ||||
|       getList () { | ||||
|  | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .visit { | ||||
|     .visit-list { | ||||
|       .visit-item { | ||||
|         padding: 10px 0; | ||||
|         border-bottom: 1px solid #eee; | ||||
|  | ||||
|         &:first-child { | ||||
|           padding-top: 0; | ||||
|         } | ||||
|  | ||||
|         &:last-child { | ||||
|           border-bottom: none; | ||||
|         } | ||||
|  | ||||
|         .visit-status { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           font-size: 14px; | ||||
|  | ||||
|           span { | ||||
|             color: #333; | ||||
|           } | ||||
|  | ||||
|           i { | ||||
|             color: #999; | ||||
|             font-style: normal; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         & > p { | ||||
|           line-height: 1.4; | ||||
|           margin-bottom: 4px; | ||||
|           text-align: justify; | ||||
|           color: #666; | ||||
|           font-size: 16px; | ||||
|         } | ||||
|  | ||||
|         .visit-item__top { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           justify-content: space-between; | ||||
|           margin-bottom: 10px; | ||||
|  | ||||
|           span { | ||||
|             font-size: 14px; | ||||
|             color: #999; | ||||
|           } | ||||
|  | ||||
|           .left { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|  | ||||
|             img { | ||||
|               width: 40px; | ||||
|               height: 40px; | ||||
|               margin-right: 10px; | ||||
|               border-radius: 50%; | ||||
|             } | ||||
|  | ||||
|             h2 { | ||||
|               font-size: 16px; | ||||
|               font-weight: 500; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										364
									
								
								packages/2.0.5/AppCodeGeneration/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										364
									
								
								packages/2.0.5/AppCodeGeneration/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,364 @@ | ||||
| <template> | ||||
|   <ai-detail v-if="pageShow"> | ||||
|     <template #title> | ||||
|       <ai-title :title="params.id ? '编辑'+colData.applicationName : '新增' + colData.applicationName" isShowBottomBorder | ||||
|                 isShowBack @onBackClick="onBack(true)"></ai-title> | ||||
|     </template> | ||||
|     <template #content> | ||||
|       <el-form ref="formData" class="ai-form" :rules="rules" :model="formData" label-width="110px" size="small"> | ||||
|         <ai-card :title="items[0].groupName" v-for="(items, indexs) in formDataList" :key="indexs" v-if="items.length"> | ||||
|           <template slot="content"> | ||||
|             <div v-for="(item, index) in items" :key="index" :style="item.grid == 1 ? 'width: 100%;' : 'width: 50%;'" | ||||
|                  class="form-div"> | ||||
|               <el-form-item :label="item.fieldName" :prop="item.fieldDbName" style="width: 100%"> | ||||
|                 <!-- 字典下拉选择 --> | ||||
|                 <template v-if="item.type == 'dict'"> | ||||
|                   <ai-select v-model="formData[item.fieldDbName]" :placeholder="item.fieldName" :selectList="dict.getDict(item.dict)" :disabled="item.disable == 1" /> | ||||
|                 </template> | ||||
|                 <!-- 单选radio --> | ||||
|                 <template v-else-if="item.type == 'radio'"> | ||||
|                   <el-radio-group v-model="formData[item.fieldDbName]" :disabled="item.disable == 1"> | ||||
|                     <el-radio :label="item.dictValue" v-for="(item, i) in dict.getDict(item.dict)" :key="i">{{ item.dictName }}</el-radio> | ||||
|                   </el-radio-group> | ||||
|                 </template> | ||||
|                 <!-- 开关onOff --> | ||||
|                 <template v-else-if="item.type == 'onOff'"> | ||||
|                   <el-switch v-model="formData[item.fieldDbName]" active-color="#26f" inactive-color="#ddd" active-value="1" inactive-value="0" :disabled="item.disable == 1"></el-switch> | ||||
|                 </template> | ||||
|                 <!-- 多选checkbox --> | ||||
|                 <template v-else-if="item.type == 'checkbox'"> | ||||
|                   <el-checkbox-group v-model="formData[item.fieldDbName]" :disabled="item.disable == 1"> | ||||
|                     <el-checkbox v-for="(item, i) in dict.getDict(item.dict)" :label="item.dictValue" :key="i"> | ||||
|                       {{ item.dictName }} | ||||
|                     </el-checkbox> | ||||
|                   </el-checkbox-group> | ||||
|                 </template> | ||||
|                 <!-- 身份证输入框 --> | ||||
|                 <template v-else-if="item.type == 'idNumber'"> | ||||
|                   <ai-id v-model="formData[item.fieldDbName]" :disabled="item.disable == 1" /> | ||||
|                 </template> | ||||
|                 <!-- input输入框 --> | ||||
|                 <template v-else-if="item.type == 'input' || item.type == 'name' || item.type == 'phone'"> | ||||
|                   <el-input v-model="formData[item.fieldDbName]" :placeholder="'请输入'+item.fieldName" clearable :disabled="item.disable == 1" | ||||
|                             :maxlength="item.maxLength" show-word-limit></el-input> | ||||
|                 </template> | ||||
|                 <!-- number 输入框 --> | ||||
|                 <template v-else-if="item.type == 'number'"> | ||||
|                   <el-input-number v-model="formData[item.fieldDbName]" :label="'请输入'+item.fieldName" :disabled="item.disable == 1" :precision="item.decimalPlaces" :max="item.maxValue" :min="item.minValue"></el-input-number> | ||||
|                 </template> | ||||
|                 <!-- textarea输入框 --> | ||||
|                 <template v-else-if="item.type == 'textarea' || item.type == 'text'"> | ||||
|                   <el-input v-model="formData[item.fieldDbName]" :placeholder="'请输入'+item.fieldName" clearable :disabled="item.disable == 1" | ||||
|                             :maxlength="item.maxLength" type="textarea" show-word-limit :rows="3"></el-input> | ||||
|                 </template> | ||||
|                 <!-- 日期选择 --> | ||||
|                 <template v-else-if="item.type == 'date'"> | ||||
|                   <el-date-picker v-model="formData[item.fieldDbName]" type="date" placeholder="请选择" :disabled="item.disable == 1" | ||||
|                                   :value-format="item.timePattern"></el-date-picker> | ||||
|                 </template> | ||||
|                 <!-- 日期带时分秒选择 --> | ||||
|                 <template v-else-if="item.type == 'datetime'"> | ||||
|                   <el-date-picker v-model="formData[item.fieldDbName]" type="datetime" placeholder="选择日期时间" :disabled="item.disable == 1" | ||||
|                                   :value-format="item.timePattern"></el-date-picker> | ||||
|                 </template> | ||||
|                 <!-- 时间-时分秒选择 --> | ||||
|                 <template v-else-if="item.type == 'time'"> | ||||
|                   <el-time-picker v-model="formData[item.fieldDbName]" placeholder="请选择" :disabled="item.disable == 1" | ||||
|                                   :value-format="item.timePattern"></el-time-picker> | ||||
|                 </template> | ||||
|                 <!-- 附件 --> | ||||
|                 <template v-else-if="item.type == 'upload'"> | ||||
|                   <ai-uploader :instance="instance" isShowTip fileType="file" v-model="formData[item.fieldDbName]" :disabled="item.disable == 1" | ||||
|                                acceptType=".zip,.rar,.doc,.docx,.xls,.ppt,.pptx,.pdf,.txt,.jpg,.png,.xlsx" | ||||
|                                :limit="item.fileMaxCount" :maxSize="item.fileChoseSize"></ai-uploader> | ||||
|                 </template> | ||||
|                 <!-- 富文本 --> | ||||
|                 <template v-else-if="item.type == 'rtf'"> | ||||
|                   <ai-editor v-model="formData[item.fieldDbName]" :instance="instance"/> | ||||
|                 </template> | ||||
|                 <!-- 地区选择 --> | ||||
|                 <template v-else-if="item.type == 'area'"> | ||||
|                   <ai-area-get :instance="instance" v-model="formData[item.fieldDbName]" :name.sync="formData[item.fieldDbName +'_name']" :disabled="item.disable == 1"/> | ||||
|                 </template> | ||||
|                 <!-- 人员选择 --> | ||||
|                 <div class="especial" v-else-if="item.type == 'user'"> | ||||
|                   <span class="icon"> </span> | ||||
|                   <span class="people">{{ item.fieldName }}:</span> | ||||
|                   <ai-wechat-selecter slot="append" isShowUser :instance="instance" | ||||
|                                       v-model="formData[item.fieldDbName]"></ai-wechat-selecter> | ||||
|                 </div> | ||||
|               </el-form-item> | ||||
|             </div> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </el-form> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button class="delete-btn footer-btn" @click="onBack">取消</el-button> | ||||
|       <el-button class="footer-btn" type="primary" @click="submit('formData')">提交</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'Add', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     params: Object, | ||||
|     dict: Object, | ||||
|     appId: String, | ||||
|     backType: String, | ||||
|     configs: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       formData: {}, | ||||
|       pickerOptions0: { | ||||
|         disabledDate(time) { | ||||
|           return time.getTime() < Date.now() - 8.64e7; | ||||
|         } | ||||
|       }, | ||||
|       formDataList: [], | ||||
|       pageShow: false, | ||||
|       colData: {}, | ||||
|       areaId: '' | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     rules() { | ||||
|       let rules = {} | ||||
|       this.colData?.tableInfos?.map(e => { | ||||
|         rules[e.fieldDbName] = [] | ||||
|         if (e.mustFill == 1) {//是否必填 | ||||
|           rules[e.fieldDbName]?.push({required: true, message: e.fieldTips}) | ||||
|         } | ||||
|       }) | ||||
|       return rules | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getFormData() | ||||
|     if (this.params.id) { | ||||
|       this.getDetail() | ||||
|     }  | ||||
|   }, | ||||
|   methods: { | ||||
|     initForm(data) { | ||||
|       this.colData = data | ||||
|       let dictList = [] | ||||
|       let formList = {} | ||||
|       data.tableInfos.map((item) => { | ||||
|         let colItem | ||||
|         if (item.dictionaryCode) { | ||||
|           dictList.push(item.dictionaryCode) | ||||
|         } | ||||
|         if (item.dictionaryCode && item.type != 'radio' && item.type != 'checkbox' && item.type != 'onOff') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             type: 'dict', | ||||
|             dict: item.dictionaryCode | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = item.defaultValue || '' | ||||
|           } | ||||
|         } else if (item.type == 'radio') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             dict: item.dictionaryCode, | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = item.defaultValue || '' | ||||
|           } | ||||
|         } else if (item.type == 'checkbox') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             dict: item.dictionaryCode, | ||||
|             fieldValue: [] | ||||
|           } | ||||
|           if (!this.params.id && item.defaultValue) { | ||||
|             var val = item.defaultValue?.split('`') | ||||
|             colItem.fieldValue = val | ||||
|           } | ||||
|  | ||||
|         } else if (item.type == 'onOff') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = item.defaultValue || 0 | ||||
|           } | ||||
|         } else if (item.type == 'number') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             type: item.type, | ||||
|             min: item.minValue || '', | ||||
|             max: item.maxValue || '' | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = Number(item.defaultValue) || 0 | ||||
|           } | ||||
|         }else { | ||||
|           if (item.type == 'date' && !item.timePattern) { | ||||
|             item.timePattern = 'yyyy-MM-dd' | ||||
|           } | ||||
|           if (item.type == 'datetime' && !item.timePattern) { | ||||
|             item.timePattern = 'yyyy-MM-dd HH:mm:ss' | ||||
|           } | ||||
|           if (item.type == 'time' && !item.timePattern) { | ||||
|             item.timePattern = 'HH:mm:ss' | ||||
|           } | ||||
|  | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             type: item.type, | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = item.defaultValue || '' | ||||
|           } | ||||
|         } | ||||
|         // console.log(colItem) | ||||
|         formList[item.groupIndex]?.push(colItem) || (formList[item.groupIndex] = [colItem]) | ||||
|         this.$set(this.formData, colItem.fieldDbName, colItem.fieldValue || "") | ||||
|       }) | ||||
|       this.formDataList = Object.values(formList) | ||||
|  | ||||
|       this.$forceUpdate() | ||||
|  | ||||
|       if (dictList.length) { | ||||
|         this.getDictList(dictList) | ||||
|       } else { | ||||
|         this.pageShow = true | ||||
|       } | ||||
|     }, | ||||
|     getFormData() { | ||||
|       this.initForm(this.configs) | ||||
|     }, | ||||
|     getDetail() { | ||||
|       this.instance.post(`/app/appapplicationinfo/queryDetailById?appId=${this.appId}&id=${this.params.id}`).then((res) => { | ||||
|         if (res?.data) { | ||||
|           this.formData = res.data | ||||
|           this.configs.tableInfos.map((item) => { | ||||
|             if(item.type == 'checkbox') { | ||||
|               var checkList = this.formData[item.fieldDbName]?.split(',') | ||||
|               this.formData[item.fieldDbName] = checkList | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getDictList(listName) { | ||||
|       this.dict.load(listName.join(',')).then(() => { | ||||
|         this.pageShow = true | ||||
|       }) | ||||
|     }, | ||||
|     submit() { | ||||
|       this.$refs.formData?.validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.formDataList.map((item) => { | ||||
|             if (item.length) { | ||||
|               item.map((items) => { | ||||
|                 if (items.type == 'checkbox' && this.formData[items.fieldDbName].length) { //多选 | ||||
|                   this.formData[items.fieldDbName] = this.formData[items.fieldDbName]?.toString() | ||||
|                 } | ||||
|                 if (items.type == 'upload' && this.formData[items.fieldDbName].length) { //附件 只传id | ||||
|                   var files = [] | ||||
|                   this.formData[items.fieldDbName].map((item) => { | ||||
|                     files.push(item.id) | ||||
|                   }) | ||||
|                   this.formData[items.fieldDbName] = files.join(',') | ||||
|                 } | ||||
|                 if(items.type == 'area' && this.formData[items.fieldDbName]) { | ||||
|                   var area = [] | ||||
|                   area.push(this.formData[items.fieldDbName]) | ||||
|                   area.push(this.formData[items.fieldDbName+'_name']) | ||||
|                   this.formData[items.fieldDbName] = area.join('_') | ||||
|                 } | ||||
|               }) | ||||
|             } | ||||
|           }) | ||||
|           this.instance.post(`/app/appapplicationinfo/addOrUpdate?appId=${this.appId}`, { | ||||
|             ...this.formData, | ||||
|             id: this.params.id || '' | ||||
|           }).then((res) => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('提交成功') | ||||
|               setTimeout(() => { | ||||
|                 this.onBack(true) | ||||
|               }, 600) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     onBack(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: this.backType == 'Detail' ? 'detail' : 'list', | ||||
|         params: this.params, | ||||
|         isRefresh: !!isRefresh, | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| ::v-deep .ai-card{ | ||||
|   width: 100%; | ||||
| } | ||||
| .form-div { | ||||
|   display: inline-block; | ||||
|   vertical-align: top; | ||||
| } | ||||
|  | ||||
| .especial { | ||||
|   margin-bottom: 12px; | ||||
|  | ||||
|   .icon { | ||||
|     vertical-align: top; | ||||
|     display: inline-block; | ||||
|     padding-top: 5px; | ||||
|     margin-left: 20px; | ||||
|     color: #f46; | ||||
|   } | ||||
|  | ||||
|   .people { | ||||
|     display: inline-block; | ||||
|     font-size: 14px; | ||||
|     color: #666; | ||||
|     padding-right: 12px; | ||||
|     vertical-align: top; | ||||
|     width: 64px; | ||||
|     word-break: break-all; | ||||
|     box-sizing: border-box; | ||||
|   } | ||||
|  | ||||
|   .AiWechatSelecter { | ||||
|     display: inline-block; | ||||
|     margin-left: 3px; | ||||
|   } | ||||
|  | ||||
|   .hint { | ||||
|     font-size: 14px; | ||||
|     color: #999; | ||||
|     margin-left: 16px; | ||||
|   } | ||||
|  | ||||
|   .mar-r40 { | ||||
|     margin-right: 40px; | ||||
|   } | ||||
|  | ||||
|   .w80 { | ||||
|     width: 80px; | ||||
|     text-align: right; | ||||
|     color: #888; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .AiWechatSelecter { | ||||
|   width: calc(100% - 120px); | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										236
									
								
								packages/2.0.5/AppCodeGeneration/components/Detail.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								packages/2.0.5/AppCodeGeneration/components/Detail.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,236 @@ | ||||
| <template> | ||||
|   <ai-detail v-if="pageShow"> | ||||
|     <template #title> | ||||
|       <ai-title :title="colData.applicationName+'详情'" isShowBottomBorder isShowBack @onBackClick="onBack(true)"></ai-title> | ||||
|     </template> | ||||
|     <template #content> | ||||
|       <AiSidebar :tabTitle="tabTitle" v-model="currIndex" v-if="appType"></AiSidebar> | ||||
|       <ai-card v-show="currIndex === 0" :title="items[0].groupName" v-for="(items, indexs) in formDataList" :key="indexs"> | ||||
|         <template slot="content"> | ||||
|           <ai-wrapper class="mar-t16" label-width="80px" :columnsNumber="1"> | ||||
|             <div v-for="(item, index) in items" :key="index" :style="item.grid == 0.5 ? 'width: 50%;': 'width: 100%;'" class="form-div"> | ||||
|               <ai-info-item :label="item.fieldName+ ':'"> | ||||
|                 <span v-if="item.dict && item.type != 'checkbox'">{{$dict.getLabel(item.dict, formData[item.fieldDbName]) || '-'}}</span> | ||||
|                 <span v-if="!item.dict && item.type != 'rtf' && item.type != 'upload' && item.type != 'area'">{{formData[item.fieldDbName]}}</span> | ||||
|                 <span v-if="item.type == 'checkbox'">{{formData[item.fieldDbName]}}</span> | ||||
|                 <span v-if="item.type == 'rtf'" v-html="formData[item.fieldDbName]"></span> | ||||
|                 <ai-file-list :fileList="formData[item.fieldDbName]" v-if="item.type == 'upload'" :fileOps="{name: 'name', size: 'fileSizeStr'}"></ai-file-list> | ||||
|                 <span v-if="item.type == 'area'" v-html="formData[item.fieldDbName+'_name']"></span> | ||||
|               </ai-info-item> | ||||
|             </div> | ||||
|           </ai-wrapper> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       <component :is="component" v-if="currIndex === 1"></component> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import { mapState } from 'vuex' | ||||
|   import Visit from './../app/visit/Visit' | ||||
|  | ||||
|   export default { | ||||
|     name: 'Detail', | ||||
|  | ||||
|     props: { | ||||
|       dict: Object, | ||||
|       appId: String, | ||||
|       params: Object, | ||||
|       configs: Object, | ||||
|       appType: String, | ||||
|       instance: Function | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       Visit | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         formData: {}, | ||||
|         colData: {}, | ||||
|         formDataList: [], | ||||
|         tabTitle: ['人员信息'], | ||||
|         pageShow: false, | ||||
|         currIndex: 0, | ||||
|         component: '' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       ...mapState(['user']), | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       if (!this.appType) return | ||||
|  | ||||
|       if (this.appType === '0') { | ||||
|         this.component = 'Visit' | ||||
|       } | ||||
|       this.dict.load('diyAppType').then(() => { | ||||
|         this.tabTitle.push(this.dict.getLabel('diyAppType', this.appType)) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.getFormData() | ||||
|       this.getDetail() | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       initForm (data) { | ||||
|         this.colData = data | ||||
|         let dictList = [] | ||||
|         let formList = {} | ||||
|         data.tableInfos.map((item) => { | ||||
|           let colItem | ||||
|           if (item.dictionaryCode) { | ||||
|             dictList.push(item.dictionaryCode) | ||||
|           } | ||||
|           if (item.dictionaryCode && item.type != 'radio' && item.type != 'checkbox') { | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               type: 'dict', | ||||
|               dict: item.dictionaryCode | ||||
|             } | ||||
|           } else if (item.type == 'radio') { | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               dict: item.dictionaryCode, | ||||
|             } | ||||
|           } else if (item.type == 'checkbox') { | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               dict: item.dictionaryCode, | ||||
|               fieldValue: item.fieldValue?.split(',') || [] | ||||
|             } | ||||
|           } else if (item.type == 'onOff') { | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               fieldValue: 0 | ||||
|             } | ||||
|           } else { | ||||
|             if (item.type == 'date' && !item.timePattern) { | ||||
|               item.timePattern = 'yyyy-MM-dd' | ||||
|             } | ||||
|             if (item.type == 'datetime' && !item.timePattern) { | ||||
|               item.timePattern = 'HH:mm:ss yyyy-MM-dd' | ||||
|             } | ||||
|             if (item.type == 'time' && !item.timePattern) { | ||||
|               item.timePattern = 'HH:mm:ss' | ||||
|             } | ||||
|  | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               type: item.type, | ||||
|             } | ||||
|           } | ||||
|           formList[item.groupIndex]?.push(colItem) || (formList[item.groupIndex] = [colItem]) | ||||
|           this.$set(this.formData, colItem.fieldDbName, colItem.fieldValue || "") | ||||
|         }) | ||||
|         this.formDataList = Object.values(formList) | ||||
|  | ||||
|         this.$forceUpdate() | ||||
|  | ||||
|         if (dictList.length) { | ||||
|           this.getDictList(dictList) | ||||
|         } else { | ||||
|           this.pageShow = true | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       getFormData () { | ||||
|         this.initForm(this.configs) | ||||
|       }, | ||||
|  | ||||
|       getDetail () { | ||||
|         this.instance.post(`/app/appapplicationinfo/queryDetailById?appId=${this.appId}&id=${this.params.id}`).then((res) => { | ||||
|           if (res?.data) { | ||||
|             this.formData = res.data | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getDictList (listName) { | ||||
|         this.dict.load(listName.join(',')).then(() => { | ||||
|           this.pageShow = true | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onBack (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'list', | ||||
|           isRefresh: !!isRefresh, | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       toEdit () { | ||||
|         this.$emit('change', { | ||||
|           type: 'Add', | ||||
|           params: this.params, | ||||
|           backType: 'Detail' | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .form-div{ | ||||
|     display: inline-block; | ||||
|   } | ||||
|   .especial { | ||||
|     margin-bottom: 12px; | ||||
|     .icon { | ||||
|       vertical-align: top; | ||||
|       display: inline-block; | ||||
|       padding-top: 5px; | ||||
|       margin-left: 20px; | ||||
|       color: #f46; | ||||
|     } | ||||
|     .people { | ||||
|       display: inline-block; | ||||
|       font-size: 14px; | ||||
|       color: #666; | ||||
|       margin-right: 16px; | ||||
|       vertical-align: top; | ||||
|     } | ||||
|     .AiWechatSelecter { | ||||
|       display: inline-block; | ||||
|       margin-left: 3px; | ||||
|     } | ||||
|     .hint { | ||||
|       font-size: 14px; | ||||
|       color: #999; | ||||
|       margin-left: 16px; | ||||
|     } | ||||
|     .mar-r40{ | ||||
|       margin-right: 40px; | ||||
|     } | ||||
|     .w80{ | ||||
|       width: 80px; | ||||
|       text-align: right; | ||||
|       color: #888; | ||||
|     } | ||||
|   } | ||||
|   .add-icon{ | ||||
|     text-align: right; | ||||
|     cursor: pointer; | ||||
|     i{ | ||||
|       font-size: 14px; | ||||
|     } | ||||
|   } | ||||
|   .color1{ | ||||
|     color:#4B87FE; | ||||
|   } | ||||
|   .color2{ | ||||
|     color:#2EA222; | ||||
|   } | ||||
|   .color3{ | ||||
|     color:#999999; | ||||
|   } | ||||
|   .AiWechatSelecter{ | ||||
|     width: calc(100% - 150px); | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										302
									
								
								packages/2.0.5/AppCodeGeneration/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								packages/2.0.5/AppCodeGeneration/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,302 @@ | ||||
| <template> | ||||
|   <ai-list v-if="pageShow"> | ||||
|     <template slot="title"> | ||||
|       <ai-title :title="configs.applicationName" isShowBottomBorder></ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar v-if="searchList.length"> | ||||
|         <template #left> | ||||
|           <div v-for="(item, index) in searchList" :key="index"> | ||||
|             <ai-select | ||||
|               v-model="search[item.searchValue]" | ||||
|               :placeholder="'请选择'+item.label" clearable | ||||
|               @change="$forceUpdate();(page.current = 1), getList()" | ||||
|                        :selectList="dict.getDict(item.dict)" | ||||
|                        v-if="item.type == 'dict'"> | ||||
|             </ai-select> | ||||
|             <ai-search v-else-if="item.type == 'date'" :label="item.label"> | ||||
|               <el-date-picker size="small" v-model="search[item.searchValue]" type="daterange" range-separator="至" | ||||
|                               start-placeholder="开始日期" end-placeholder="结束日期" | ||||
|                               @change="$forceUpdate();(page.current = 1), getList()" | ||||
|                               value-format="yyyy-MM-dd"/> | ||||
|             </ai-search> | ||||
|             <ai-search v-else-if="item.type == 'time'" :label="item.label"> | ||||
|               <el-time-picker is-range size="small" v-model="search[item.searchValue]" range-separator="至" | ||||
|                               start-placeholder="开始时间" end-placeholder="结束时间" placeholder="选择时间范围" | ||||
|                               @change="$forceUpdate();(page.current = 1), getList()" | ||||
|                               value-format="HH:mm:ss"></el-time-picker> | ||||
|             </ai-search> | ||||
|             <ai-search v-else-if="item.type == 'area'" :label="item.label"> | ||||
|               <ai-area-get :instance="instance" v-model="search[item.searchValue]"/> | ||||
|             </ai-search> | ||||
|           </div> | ||||
|         </template> | ||||
|         <template #right v-if="showRightInput"> | ||||
|           <el-input :placeholder="placeholder" v-model="search.searchParam" size="small" | ||||
|                     @change="$forceUpdate();(page.current = 1), getList()" clearable prefix-icon="iconfont iconSearch"/> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-search-bar> | ||||
|         <template #left> | ||||
|           <el-button type="primary" icon="iconfont iconAdd" size="small" | ||||
|                      v-if="configs.insertEnable == 1" @click="toAdd('', 'Add')">添加 | ||||
|           </el-button> | ||||
|           <el-button icon="iconfont iconDelete" size="small" :disabled="ids.length == 0" | ||||
|                      v-if="configs.batchDelEnable == 1" @click="delAll()">删除 | ||||
|           </el-button> | ||||
|         </template> | ||||
|         <template #right> | ||||
|           <ai-import :instance="instance" v-if="configs.importEnable == 1" type="appapplicationinfo" | ||||
|                      :importParams="{appId}" :tplParams="{appId}" :name="configs.applicationName" @success="getList()"> | ||||
|             <el-button icon="iconfont iconImport">导入</el-button> | ||||
|           </ai-import> | ||||
|           <el-button icon="iconfont iconExported" size="small" v-if="configs.exportEnalbe == 1" @click="down()" | ||||
|                     >导出 | ||||
|           </el-button> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table class="ai-table" :tableData="tableData" :col-configs="colConfigs" :total="page.total" | ||||
|                 :current.sync="page.current" :size.sync="page.size" @getList="getList" :dict="dict" | ||||
|                 @selection-change="(v) => (ids = v.map((e) => e.id))"> | ||||
|         <el-table-column v-for="(item, indexs) in colConfigs" :key="indexs" :slot="item.slot" :label="item.label" | ||||
|                          show-overflow-tooltip | ||||
|                          align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div v-if="item.type != 'checkbox' && item.dict"> | ||||
|               {{ $dict.getLabel(item.dict, row[item.fieldDbName]) || '-' }} | ||||
|             </div> | ||||
|             <div v-if="item.type == 'rtf'" v-html="row[item.fieldDbName]"></div> | ||||
|             <div v-if="item.type == 'checkbox'">{{ row[item.fieldDbName] }}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column slot="options" label="操作" align="center" width="200"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-options"> | ||||
|               <el-button type="text" @click="toDetail(row, 'Detail')">详情</el-button> | ||||
|               <el-button type="text" @click="toDetail(row, 'Add')" v-if="configs.editEnable == 1">编辑</el-button> | ||||
|               <el-button type="text" @click="del(row.id)" v-if="configs.deleteEnable == 1">删除</el-button> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: 'List', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     appId: String, | ||||
|     configs: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       pageShow: false, | ||||
|       tableData: [], | ||||
|       colConfigs: [], | ||||
|       page: { | ||||
|         size: 10, | ||||
|         current: 1, | ||||
|         total: 0, | ||||
|       }, | ||||
|       search: { | ||||
|         searchParam: '', | ||||
|       }, | ||||
|       searchList: [], | ||||
|       ids: [], | ||||
|       showRightInput: false, | ||||
|       placeholder: '请输入', | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.initConfigs() | ||||
|   }, | ||||
|   methods: { | ||||
|     initConfigs() { | ||||
|       var dictList = [] | ||||
|       var colList = [] | ||||
|       var searchList = [] | ||||
|       var placeholderList = [] | ||||
|       this.configs.showListFields.map((item) => { | ||||
|         var colItem | ||||
|         if (item.dictionaryCode) { | ||||
|           dictList.push(item.dictionaryCode) | ||||
|           colItem = { | ||||
|             slot: item.fieldDbName, | ||||
|             label: item.fieldName, | ||||
|             dict: item.dictionaryCode, | ||||
|             fieldDbName: item.fieldDbName, | ||||
|             type: item.type | ||||
|           } | ||||
|         } else if (item.type == 'rtf') { | ||||
|           colItem = {label: item.fieldName, type: item.type, slot: item.fieldDbName, fieldDbName: item.fieldDbName} | ||||
|         } else if (item.type == 'area') { | ||||
|           colItem = {prop: item.fieldDbName + '_name', label: item.fieldName, align: "center"} | ||||
|         } else { | ||||
|           colItem = {prop: item.fieldDbName, label: item.fieldName, align: "center"} | ||||
|         } | ||||
|         colList.push(colItem) | ||||
|       }) | ||||
|       this.configs.fuzzyQueryFields.map((item) => { | ||||
|         var searchItem = {} | ||||
|         if (item.dictionaryCode) { | ||||
|           searchItem = { | ||||
|             type: 'dict', | ||||
|             label: item.fieldName, | ||||
|             dict: item.dictionaryCode, | ||||
|             searchValue: item.fieldDbName | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (item.type == 'input' || item.type == 'name' || item.type == 'idNumber' || item.type == 'phone') { | ||||
|           placeholderList.push(item.fieldName) | ||||
|           this.showRightInput = true | ||||
|         } | ||||
|  | ||||
|         if (item.type == 'date') { | ||||
|           searchItem = { | ||||
|             type: 'date', | ||||
|             label: item.fieldName, | ||||
|             searchValue: item.fieldDbName | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (item.type == 'time') { | ||||
|           searchItem = { | ||||
|             type: 'time', | ||||
|             label: item.fieldName, | ||||
|             searchValue: item.fieldDbName | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (item.type == 'area') { | ||||
|           searchItem = { | ||||
|             type: 'area', | ||||
|             label: item.fieldName, | ||||
|             searchValue: item.fieldDbName | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         this.$set(this.search, item.fieldDbName, '') | ||||
|         searchList.push(searchItem) | ||||
|       }) | ||||
|  | ||||
|       this.colConfigs = colList | ||||
|       this.searchList = searchList | ||||
|       this.$forceUpdate() | ||||
|  | ||||
|       var text = placeholderList.join('/') | ||||
|       this.placeholder = this.placeholder + text | ||||
|  | ||||
|       if (this.configs.batchDelEnable == 1) { | ||||
|         this.colConfigs.unshift({type: 'selection', width: 100}) | ||||
|       } | ||||
|       if (dictList.length) { | ||||
|         this.getDictList(dictList) | ||||
|       } else { | ||||
|         this.pageShow = true | ||||
|         this.getList() | ||||
|       } | ||||
|     }, | ||||
|     getDictList(listName) { | ||||
|       this.dict.load(listName.join(',')).then(() => { | ||||
|         this.pageShow = true | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|     getList() { | ||||
|       this.instance.post(`/app/appapplicationinfo/list?appId=${this.appId}¤t=${this.page.current}&size=${this.page.size}`, {...this.search}).then((res) => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data.records | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     toDetail(item, type) { | ||||
|       this.$emit('change', { | ||||
|         type: type, | ||||
|         params: item, | ||||
|         backType: 'List' | ||||
|       }) | ||||
|     }, | ||||
|     toAdd() { | ||||
|       this.$emit('change', { | ||||
|         type: 'Add', | ||||
|         params: { | ||||
|           type: 'Add', | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     del(id) { | ||||
|       this.$confirm("删除后不可恢复,是否要删除?", { | ||||
|         type: 'error' | ||||
|       }).then(() => { | ||||
|         this.instance.post(`/app/appapplicationinfo/delete?appId=${this.appId}&ids=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success("删除成功!"); | ||||
|             this.getList(); | ||||
|           } | ||||
|         }) | ||||
|       }); | ||||
|     }, | ||||
|     delAll() { | ||||
|       if (this.ids.length > 100) { | ||||
|         return this.$message.error("删除的数据最多不能超过100条!"); | ||||
|       } | ||||
|       var id = this.ids.join(',') | ||||
|       this.del(id) | ||||
|     }, | ||||
|  | ||||
|     reset() { | ||||
|       Object.keys(this.search).forEach((e) => { | ||||
|         this.search[e] = '' | ||||
|       }) | ||||
|       this.getList() | ||||
|     }, | ||||
|     down() { | ||||
|       var id = '' | ||||
|       if (this.ids.length) { | ||||
|         id = this.ids.join(',') | ||||
|       } | ||||
|       this.instance.post(`/app/appapplicationinfo/export?appId=${this.appId}&ids=${id}`, this.search, { | ||||
|         responseType: 'blob', | ||||
|         timeout: 100000 | ||||
|       }).then(res => { | ||||
|         if (res?.type == "application/json") { | ||||
|           let reader = new FileReader() | ||||
|           reader.readAsText(res, "utf-8") | ||||
|           reader.onload = e => { | ||||
|             if (e.target.readyState === 2) { | ||||
|               let ret = JSON.parse(e.target.result) | ||||
|               if (ret?.code == 0) { | ||||
|                 this.$message.success(ret.msg) | ||||
|               } else this.$message.error(ret.msg) | ||||
|             } | ||||
|           } | ||||
|         } else { | ||||
|           const link = document.createElement('a') | ||||
|           let blob = new Blob([res], {type: res.type}) | ||||
|           link.style.display = 'none' | ||||
|           link.href = URL.createObjectURL(blob) | ||||
|           link.setAttribute('download', this.configs.applicationName + '.xls') | ||||
|           document.body.appendChild(link) | ||||
|           link.click() | ||||
|           document.body.removeChild(link) | ||||
|         } | ||||
|       }).catch((err) => { | ||||
|         this.$error.success(err) | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .mar-b10 { | ||||
|   margin-bottom: 10px; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										59
									
								
								packages/2.0.5/AppCommunityManage/AppCommunityManage.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								packages/2.0.5/AppCommunityManage/AppCommunityManage.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| <template> | ||||
|   <section class="AppCommunityManage ailist-wrapper"> | ||||
|     <component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict" /> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from './components/List' | ||||
| import Add from './components/Add' | ||||
|  | ||||
| export default { | ||||
|   name: 'AppCommunityManage', | ||||
|   label: '小区管理', | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: 'List', | ||||
|       params: {}, | ||||
|       include: [], | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     Add, | ||||
|     List, | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === 'add') { | ||||
|         this.component = 'Add' | ||||
|         this.params = data.params | ||||
|       } | ||||
|  | ||||
|       if (data.type === 'list') { | ||||
|         this.component = 'List' | ||||
|         this.params = data.params | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getList() | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppCommunityManage { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										244
									
								
								packages/2.0.5/AppCommunityManage/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								packages/2.0.5/AppCommunityManage/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,244 @@ | ||||
| <template> | ||||
|   <ai-detail showFooter class="add-detail"> | ||||
|     <template slot="title"> | ||||
|       <ai-title :title="isEdit ? '编辑小区信息' : '添加小区'" :isShowBack="true" @onBackClick="cancel()" :isShowBottomBorder="true"></ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <div class="add-form"> | ||||
|         <ai-bar title="基础信息"></ai-bar> | ||||
|         <el-form label-width="110px" style="padding-bottom: 80px;" :model="form" ref="form"> | ||||
|           <el-form-item label="小区名称" prop="communityName" :rules="[{ required: true, message: '请输入小区名称', trigger: 'blur' }]"> | ||||
|             <el-input size="small" v-model="form.communityName" :maxlength="50" placeholder="请输入小区名称"></el-input> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="行政归属" prop="areaId" :rules="[{ required: true, message: '请选择行政归属', trigger: 'blur' }]"> | ||||
|             <ai-area-get :instance="instance" v-model="form.areaId" :root="user.info.areaId" @select="handleAreaSelect" /> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="小区地址" prop="address" :rules="[{ required: true, message: '请输入小区地址', trigger: 'blur' }]"> | ||||
|             <el-input size="small" v-model="form.address" placeholder="请输入小区名称" clearable=""></el-input> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="所属网格" prop="girdInfoList" style="margin-top: 8px;" :rules="[{ required: true, message: '请选择所属网格', trigger: 'blur' }]">                                                                      | ||||
|             <el-tag | ||||
|               :key="index" | ||||
|               v-for="(tag,index) in form.girdInfoList" | ||||
|               closable | ||||
|               :disable-transitions="false" | ||||
|               @close="handleClose(tag)"> | ||||
|               {{tag.girdName}} | ||||
|             </el-tag>                                       | ||||
|             <el-button size="small" @click="showGrid=true">选择网格</el-button>                                                                           | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </div> | ||||
|       <ai-dialog title="选择网格" :visible.sync="showGrid" :customFooter="true"  :destroyOnClose="true"  @opened="beforeSelectTree"  border  width="720px"> | ||||
|         <div class="grid"> | ||||
|           <el-tree :data="treeObj.treeList"  :props="treeObj.defaultProps" node-key="id"  ref="tree" :check-strictly="true" show-checkbox | ||||
|             :default-checked-keys="treeObj.checkedKeys" default-expand-all  highlight-current>                   | ||||
|           </el-tree>  | ||||
|         </div> | ||||
|         <div class="dialog-footer" slot="footer" > | ||||
|           <el-button  size="medium" @click="showGrid=false">取消</el-button> | ||||
|           <el-button  type="primary" size="medium" @click="getCheckedTree()">确认</el-button> | ||||
|         </div> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|     <template slot="footer" class="footer"> | ||||
|       <el-button class="delete-btn footer-btn" @click="cancel(false)">取消</el-button> | ||||
|       <el-button class="footer-btn" type="primary" @click="onSubmit('0')">保存</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'Add', | ||||
|  | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     instance: Function, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       gridList: [], | ||||
|       girdId: '', | ||||
|       subGridId: '', | ||||
|       subGridList: [], | ||||
|       sonGridList: [], | ||||
|       form: { | ||||
|         communityName: '', | ||||
|         areaName: '', | ||||
|         areaId: '', | ||||
|         girdId: '', | ||||
|         dealOpinion: '', | ||||
|         recordUser: '', | ||||
|         address: '', | ||||
|         girdInfoList: [], | ||||
|         girdName: '', | ||||
|       }, | ||||
|       showGrid: false, | ||||
|       treeObj: { | ||||
|         treeList: [], | ||||
|         defaultProps: { | ||||
|           children: "girdList", | ||||
|           label: "girdName", | ||||
|         }, | ||||
|         checkedKeys: [], | ||||
|       }, | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     isEdit() { | ||||
|       return !!this.params.id | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     this.dict.load('cardType', 'sex', 'nation').then(() => { | ||||
|       if (this.params && this.params.id) { | ||||
|         this.getInfo(this.params.id) | ||||
|       } | ||||
|     }) | ||||
|   }, | ||||
|   methods: { | ||||
|     beforeSelectTree() { | ||||
|       this.treeObj.checkedKeys = []; | ||||
|       this.instance.post(`/app/appgirdinfo/listAll`, null, null).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.treeObj.treeList = res.data; | ||||
|           if(this.form.girdInfoList.length) { | ||||
|             this.form.girdInfoList.map((e) => { | ||||
|               this.treeObj.checkedKeys.push(e.id); | ||||
|             }); | ||||
|           } | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     getCheckedTree() { | ||||
|       this.form.girdInfoList = this.$refs.tree.getCheckedNodes(); | ||||
|       this.showGrid = false; | ||||
|     }, | ||||
|     handleClose(tag) { | ||||
|       this.form.girdInfoList.splice(this.form.girdInfoList.indexOf(tag), 1); | ||||
|     }, | ||||
|     getInfo(id) { | ||||
|       this.instance.post(`/app/appcommunityinfo/queryDetailById?id=${id}`).then((res) => { | ||||
|         if (res.code === 0) { | ||||
|           this.girdId = res.data.girdId0 | ||||
|           this.form.communityName = res.data.communityName | ||||
|           this.form.address = res.data.address | ||||
|           this.form.areaName = res.data.areaName | ||||
|           this.form.girdId = res.data.girdId | ||||
|           this.form.girdName = res.data.girdName | ||||
|           this.form.girdInfoList = [{id:res.data.girdId, girdName: res.data.girdName}] | ||||
|           this.$set(this.form, 'areaId', res.data.areaId) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onSubmit() { | ||||
|       this.$refs.form.validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.form.girdName = this.form.girdInfoList[0].girdName | ||||
|           this.form.girdId = this.form.girdInfoList[0].id | ||||
|           this.instance | ||||
|             .post(`/app/appcommunityinfo/addOrUpdate`, { | ||||
|               ...this.form, | ||||
|               id: this.params ? this.params.id : '', | ||||
|             }) | ||||
|             .then((res) => { | ||||
|               if (res.code === 0) { | ||||
|                 this.$message.success('提交成功') | ||||
|                 setTimeout(() => { | ||||
|                   this.cancel(true) | ||||
|                 }, 800) | ||||
|               } | ||||
|             }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     cancel(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: !!isRefresh, | ||||
|       }) | ||||
|     }, | ||||
|     handleAreaSelect(v) { | ||||
|       this.form.areaName = v?.[0]?.label | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .add-detail { | ||||
|   height: 100%; | ||||
|   overflow: hidden; | ||||
|   background: #f2f4f6 !important; | ||||
|  | ||||
|   .add-form__item { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-form-item__label { | ||||
|     padding-right: 40px; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-detail__footer { | ||||
|     background: #fff !important; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-detail__content--active { | ||||
|     padding: 20px; | ||||
|  | ||||
|     .ai-detail__content--wrapper { | ||||
|       width: 100%; | ||||
|     } | ||||
|  | ||||
|     .aibar { | ||||
|       padding: 0 16px; | ||||
|     } | ||||
|  | ||||
|     .el-form { | ||||
|       padding: 0 96px 0 50px; | ||||
|     } | ||||
|  | ||||
|     .add-form { | ||||
|       background: #fff; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-wrapper { | ||||
|     align-items: inherit !important; | ||||
|   } | ||||
|  | ||||
|   .user-wrapper { | ||||
|     display: flex; | ||||
|     justify-content: space-between; | ||||
|   } | ||||
|  | ||||
|   .avatar { | ||||
|     width: 100px; | ||||
|     height: 100px; | ||||
|     object-fit: contain; | ||||
|     border-radius: 10px; | ||||
|   } | ||||
|  | ||||
|   .footer-btn { | ||||
|     width: 130px; | ||||
|   } | ||||
|  | ||||
|   .el-form { | ||||
|     padding-bottom: 80px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										202
									
								
								packages/2.0.5/AppCommunityManage/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								packages/2.0.5/AppCommunityManage/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,202 @@ | ||||
| <template> | ||||
|   <ai-list class="AppPetitionManage"> | ||||
|     <template slot="title"> | ||||
|       <ai-title title="小区管理" isShowBottomBorder /> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar class="search-bar" bottomBorder> | ||||
|         <template slot="left"> | ||||
|           <el-button icon="iconfont iconAdd" type="primary" size="small" @click="onAdd('')">添加</el-button> | ||||
|           <el-button :disabled="!ids.length" icon="iconfont iconDelete" size="small" @click="removeAll">删除</el-button> | ||||
|         </template> | ||||
|         <template slot="right"> | ||||
|           <el-input v-model="search.communityName" class="search-input" size="small" @change=";(search.current = 1), getList()" placeholder="小区名称" suffix-icon="iconfont iconSearch" clearable /> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|  | ||||
|       <ai-search-bar style="margin-top: 15px;"> | ||||
|         <template #right> | ||||
|           <!-- :importParams="{ areaId: user.info && user.info.areaId }" --> | ||||
|           <ai-import :instance="instance" :dict="dict" type="appcommunityinfo" name="小区管理" @success="getList()"> | ||||
|             <el-button icon="iconfont iconImport">导入</el-button> | ||||
|           </ai-import> | ||||
|           <ai-download :instance="instance" url="/app/appcommunityinfo/listExport" :params="param" fileName="小区管理模板" :disabled="tableData.length == 0"> | ||||
|             <el-button icon="iconfont iconExported" :disabled="tableData.length == 0">导出</el-button> | ||||
|           </ai-download> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <!-- <ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" ref="aitableex" :current.sync="search.current" @selection-change="handleSelectionChange"> --> | ||||
|       <ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" ref="aitableex" :current.sync="search.current" @selection-change="(v) => (ids = v.map((e) => e.id))" :size.sync="search.size" @getList="getList"> | ||||
|         <el-table-column slot="options" label="操作" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <span class="table-btn" title="编辑" @click="toEdit(row.id)">编辑</span> | ||||
|             <span class="table-btn table-btn__remove" title="删除" @click="remove(row.id)">删除</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: 'List', | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       search: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|         communityName: '', | ||||
|       }, | ||||
|       ids: [], | ||||
|       total: 0, | ||||
|       colConfigs: [ | ||||
|         { type: 'selection' }, | ||||
|         { prop: 'communityName', label: '小区名称', align: 'center', width: '200' }, | ||||
|         { prop: 'areaName', label: '行政划分' }, | ||||
|         { prop: 'address', label: '小区地址' }, | ||||
|         { prop: 'girdName', label: '所属网格' }, | ||||
|         { prop: 'buildingNumber', label: '总楼栋数(栋)', align: 'center' }, | ||||
|         { prop: 'createUserName', label: '创建人', align: 'center' }, | ||||
|         { prop: 'createTime', label: '创建时间', align: 'center' }, | ||||
|         { slot: 'options', label: '操作', align: 'center' }, | ||||
|       ], | ||||
|       tableData: [], | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     importParams() { | ||||
|       return { | ||||
|         name: this.search.name, | ||||
|         ids: this.ids.map((v) => v.id).join(','), | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     param() { | ||||
|       let params = {} | ||||
|  | ||||
|       if (this.ids.length) { | ||||
|         params = { | ||||
|           ...params, | ||||
|           ids: this.ids, | ||||
|         } | ||||
|       } else { | ||||
|         params = { | ||||
|           ...params, | ||||
|           ...this.search, | ||||
|           ids: this.ids, | ||||
|         } | ||||
|       } | ||||
|       return params | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     this.getList() | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getList() { | ||||
|       this.instance | ||||
|         .post(`/app/appcommunityinfo/list`, null, { | ||||
|           params: { | ||||
|             ...this.search, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res?.data) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|     }, | ||||
|     handleSelectionChange(e) { | ||||
|       this.ids = e | ||||
|     }, | ||||
|  | ||||
|     toEdit(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'add', | ||||
|         params: { | ||||
|           id: id, | ||||
|         }, | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     removeAll() { | ||||
|       // this.remove(this.ids.map((v) => v.id).join(',')) | ||||
|       var id = this.ids.join(',') | ||||
|       this.remove(id) | ||||
|     }, | ||||
|  | ||||
|     remove(id) { | ||||
|       this.$confirm('确定删除该数据?').then(() => { | ||||
|         this.instance.post(`/app/appcommunityinfo/delete?ids=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('删除成功!') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onReset() { | ||||
|       this.search.current = 1 | ||||
|       this.search.communityName = '' | ||||
|  | ||||
|       this.getList() | ||||
|     }, | ||||
|  | ||||
|     onAdd(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'add', | ||||
|         params: { | ||||
|           id: id, | ||||
|         }, | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppPetitionManage { | ||||
|   ::v-deep th { | ||||
|     font-weight: bold !important; | ||||
|   } | ||||
|  | ||||
|   .table-btn { | ||||
|     color: #2266ff; | ||||
|     font-size: 14px; | ||||
|     cursor: pointer; | ||||
|  | ||||
|     &:last-child:hover { | ||||
|       color: #f46; | ||||
|     } | ||||
|  | ||||
|     &:first-child { | ||||
|       margin-right: 16px; | ||||
|  | ||||
|       &:hover { | ||||
|         opacity: 0.6; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .icon-color89B { | ||||
|     margin-right: 8px; | ||||
|     cursor: pointer; | ||||
|  | ||||
|     &:last-child { | ||||
|       margin-right: 0; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										59
									
								
								packages/2.0.5/AppEquipmentManage/AppEquipmentManage.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								packages/2.0.5/AppEquipmentManage/AppEquipmentManage.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| <template> | ||||
|   <div class="AppEquipmentManage"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from './components/List' | ||||
|  | ||||
| export default { | ||||
|   label: '广播设备管理', | ||||
|   name: 'AppEquipmentManage', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: 'List', | ||||
|       params: {}, | ||||
|       include: [], | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     List | ||||
|   }, | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === 'add') { | ||||
|         this.component = 'Add' | ||||
|         this.params = data.params | ||||
|       } | ||||
|  | ||||
|       if (data.type == 'list') { | ||||
|         this.component = 'List' | ||||
|         this.params = data.params | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getList() | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppEquipmentManage { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										207
									
								
								packages/2.0.5/AppEquipmentManage/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								packages/2.0.5/AppEquipmentManage/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| <template> | ||||
|   <section class="AppPetitionManage"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="广播设备管理" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar bottomBorder> | ||||
|           <template slot="left"> | ||||
|             <ai-select v-model="search.devStatus" placeholder="设备状态" clearable | ||||
|                        :selectList="$dict.getDict('dlbDevStatus')" @change=";(page.current = 1), getList()"></ai-select> | ||||
|             <!-- <ai-select v-model="search.bind" placeholder="是否绑定区划" clearable :selectList="$dict.getDict('yesOrNo')" @change=";(page.current = 1), getList()"></ai-select> --> | ||||
|           </template> | ||||
|           <template slot="right"> | ||||
|             <el-input v-model="search.keyword" size="small" placeholder="设备名称/设备编号" clearable | ||||
|                       @keyup.enter.native=";(page.current = 1), getList()" | ||||
|                       @clear=";(page.current = 1), (search.keyword = ''), getList()" suffix-icon="iconfont iconSearch"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-search-bar class="ai-search-ba mar-t10"> | ||||
|           <template slot="left"> | ||||
|             <!-- <el-button icon="iconfont" type="primary" size="small">数据同步</el-button> --> | ||||
|             <!-- <el-button icon="iconfont iconDelete" size="small" @click="removeAll" :disabled="ids.length == 0">删除 </el-button> --> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" ref="aitableex" | ||||
|                   :current.sync="page.current" :size.sync="page.size" @getList="getList" | ||||
|                   @selection-change="(v) => (ids = v.map((e) => e.id))"> | ||||
|           <el-table-column slot="options" label="操作" align="center" width="280" fixed="right"> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <el-button type="text" @click="close(row.id)">停播</el-button> | ||||
|               <el-button type="text" @click="bind(row)">绑定行政区划</el-button> | ||||
|               <el-button type="text" @click="locate=true">地图标绘</el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <el-dialog | ||||
|         title="绑定行政区划" | ||||
|         :visible.sync="bindVisible" | ||||
|         width="800px"> | ||||
|       <ai-area-get :instance="instance" v-model="areaId" :root="user.info.areaId" @select="handleAreaSelect"/> | ||||
|       <span slot="footer" class="dialog-footer"> | ||||
|         <el-button @click="bindVisible = false">取 消</el-button> | ||||
|         <el-button type="primary" @click="bindArea">确 定</el-button> | ||||
|       </span> | ||||
|     </el-dialog> | ||||
|     <locate-dialog v-model="locate" :ins="instance" @confirm="bindLocate"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
| import LocateDialog from "../../../monitor/components/locateDialog"; | ||||
|  | ||||
| export default { | ||||
|   name: 'List', | ||||
|   components: {LocateDialog}, | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     instance: Function, | ||||
|     params: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       isAdd: false, | ||||
|       page: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|       }, | ||||
|       total: 0, | ||||
|       search: { | ||||
|         bind: '', | ||||
|         keyword: '', | ||||
|       }, | ||||
|       id: '', | ||||
|       ids: [], | ||||
|       colConfigs: [ | ||||
|         { | ||||
|           prop: 'deviceName', | ||||
|           label: '设备名称', | ||||
|         }, | ||||
|         { | ||||
|           prop: 'areaName', | ||||
|           label: '所属行政区划', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         { | ||||
|           prop: 'serialNo', | ||||
|           label: '设备编号', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         { | ||||
|           prop: 'devStatus', | ||||
|           label: '设备状态', | ||||
|           width: '100', | ||||
|           align: 'center', | ||||
|           render: (h, {row}) => { | ||||
|             return h('span', null, this.dict.getLabel('dlbDevStatus', row.devStatus)) | ||||
|           }, | ||||
|         }, | ||||
|         { | ||||
|           prop: 'bind', | ||||
|           label: '是否绑定区划', | ||||
|           width: '120', | ||||
|           align: 'center', | ||||
|           render: (h, {row}) => { | ||||
|             return h('span', null, this.dict.getLabel('yesOrNo', row.bind)) | ||||
|           }, | ||||
|         }, | ||||
|         { | ||||
|           slot: 'options', | ||||
|           label: '操作', | ||||
|           align: 'center', | ||||
|         }, | ||||
|       ], | ||||
|       tableData: [], | ||||
|       areaId: '', | ||||
|       bindVisible: false, | ||||
|       changeInfo: {}, | ||||
|       locate: false | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     this.dict.load('dlbDevStatus', 'yesOrNo').then(() => { | ||||
|       this.getList() | ||||
|     }) | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     bind(item) { | ||||
|       this.areaId = '' | ||||
|       this.changeInfo = item | ||||
|       this.bindVisible = true | ||||
|     }, | ||||
|     handleAreaSelect(v) { | ||||
|       this.changeInfo.areaName = v?.[0]?.label | ||||
|     }, | ||||
|     bindArea() { | ||||
|       if (!this.areaId) { | ||||
|         return this.$message.error('请先选择行政区划') | ||||
|       } | ||||
|       this.changeInfo.areaId = this.areaId | ||||
|       this.instance.post(`/app/appdlbquipment/addOrUpdate`, this.changeInfo).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.$message.success('绑定行政区划成功!') | ||||
|           this.bindVisible = false | ||||
|           this.getList() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     bindLocate(locate) { | ||||
|       if (locate) { | ||||
|         let {lat, lng} = locate.location, {changeInfo} = this | ||||
|         this.instance.post("/app/appdlbquipment/addOrUpdate", { | ||||
|           ...changeInfo, lat, lng | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("地图标绘成功!") | ||||
|             this.locate = true | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|     close(id) { | ||||
|       this.$confirm('确定停播该设备?').then(() => { | ||||
|         this.instance.post(`/app/appdlbquipment/stop?deviceId=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('停播成功!') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|     getList() { | ||||
|       this.instance.post(`/app/appdlbquipment/getDlbDeviceList`, null, { | ||||
|         params: { | ||||
|           ...this.page, | ||||
|           ...this.search, | ||||
|         }, | ||||
|       }) | ||||
|       .then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.tableData = res.data.records | ||||
|           this.total = parseInt(res.data.total) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppPetitionManage { | ||||
|   height: 100%; | ||||
|  | ||||
|   .mar-t10 { | ||||
|     margin-top: 10px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										66
									
								
								packages/2.0.5/AppForm/AppForm.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								packages/2.0.5/AppForm/AppForm.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| <template> | ||||
|   <div class="doc-circulation"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import List from './components/List' | ||||
|   import Add from './components/Add' | ||||
|  | ||||
|   export default { | ||||
|     name: 'AppForm', | ||||
|     label: '配置表单', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         component: 'List', | ||||
|         params: {}, | ||||
|         include: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       Add, | ||||
|       List | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onChange (data) { | ||||
|         if (data.type === 'Add') { | ||||
|           this.component = 'Add' | ||||
|           this.params = data.params | ||||
|         } | ||||
|  | ||||
|         if (data.type === 'list') { | ||||
|           this.component = 'List' | ||||
|           this.params = data.params | ||||
|  | ||||
|           this.$nextTick(() => { | ||||
|             if (data.isRefresh) { | ||||
|               this.$refs.component.getList() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
|   .doc-circulation { | ||||
|     height: 100%; | ||||
|     background: #F3F6F9; | ||||
|     overflow: auto; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										277
									
								
								packages/2.0.5/AppForm/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								packages/2.0.5/AppForm/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,277 @@ | ||||
| <template> | ||||
|   <ai-detail class="form-add" :class="[currIndex === 1 ? 'form-add__active' : '']"> | ||||
|     <ai-title title="表单配置" slot="title" isShowBottomBorder isShowBack  @onBackClick="cancel(false)"></ai-title> | ||||
|     <template #content> | ||||
|       <div class="ai-step"> | ||||
|         <div class="ai-step__item" | ||||
|           :class="[currIndex >= index ? 'ai-step__item--active' : '']" | ||||
|           v-for="(item, index) in statusList" | ||||
|           :key="index"> | ||||
|           <div class="ai-step__item--icon" v-if="currIndex <= index"> | ||||
|             <i v-if="currIndex === index"></i> | ||||
|           </div> | ||||
|           <div class="el-icon-success" v-if="currIndex > index"> | ||||
|           </div> | ||||
|           <span>{{ item }}</span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <basic-info ref="basicInfo" v-model="basicInfo" v-show="currIndex === 0" :dict="dict" :instance="instance"></basic-info> | ||||
|       <form-layout class="form-config__wrapper" v-model="tableInfos" ref="form" v-show="currIndex === 1" :dict="dict" :instance="instance"></form-layout> | ||||
|       <form-config | ||||
|         ref="config" | ||||
|         :showListFields="showListFields" | ||||
|         :btns="btns" | ||||
|         :fuzzyQueryFields="fuzzyQueryFields" | ||||
|         :tableInfos="tableInfos" | ||||
|         :orderFields="orderFields" | ||||
|         v-if="currIndex === 2"> | ||||
|       </form-config> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button @click="cancel">取消</el-button> | ||||
|       <el-button @click="back" v-if="currIndex > 0">上一步</el-button> | ||||
|       <el-button @click="next" type="primary">{{ currIndex === 2 ? '完成' : '下一步' }}</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import BasicInfo from './BasicInfo.vue' | ||||
|   import FormLayout from './FormLayout.vue' | ||||
|   import FormConfig from './FormConfig.vue' | ||||
|   export default { | ||||
|     name: 'add', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       params: Object, | ||||
|       type: String | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       FormLayout, | ||||
|       BasicInfo, | ||||
|       FormConfig | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         currIndex: 0, | ||||
|         basicInfo: { | ||||
|           saasPlatformId: '', | ||||
|           menuLeve1Style: '', | ||||
|           saasPlatformName: '', | ||||
|           menuLevel1Name: '', | ||||
|           menuLevel2Lable: '', | ||||
|           menuLevel2Name: '' | ||||
|         }, | ||||
|         orderFields: [], | ||||
|         showListFields: [], | ||||
|         fuzzyQueryFields: [], | ||||
|         btns: [], | ||||
|         btnKeys: ['insertEnable', 'importEnable', 'exportEnalbe', 'editEnable', 'deleteEnable', 'batchDelEnable'], | ||||
|         configInfo: { | ||||
|           btns: [], | ||||
|           orderType: '0', | ||||
|           fieldName: '' | ||||
|         }, | ||||
|         info: {}, | ||||
|         tableInfos: [], | ||||
|         statusList: ['基础设置', '表单设计', '列表设计'] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       if (this.params.id) { | ||||
|         this.getInfo() | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       cancel (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'list', | ||||
|           isRefresh: isRefresh ? true : false, | ||||
|           isQuote: this.params.isQuote ? true : false | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       confirm () { | ||||
|  | ||||
|       }, | ||||
|  | ||||
|       back () { | ||||
|         this.currIndex = this.currIndex - 1 | ||||
|       }, | ||||
|  | ||||
|       confirmBasicInfo () { | ||||
|         return this.$refs.basicInfo.validate() | ||||
|       }, | ||||
|  | ||||
|       getInfo () { | ||||
|         this.instance.post(`/app/appapplicationinfo/queryDetailById?id=${this.params.id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.info = res.data | ||||
|             this.basicInfo = { | ||||
|               saasPlatformId: res.data.saasPlatformId, | ||||
|               menuLeve1Style: res.data.menuLeve1Style, | ||||
|               saasPlatformName: res.data.saasPlatformName, | ||||
|               menuLevel1Name: res.data.menuLevel1Name, | ||||
|               menuLevel2Lable: res.data.menuLevel2Lable, | ||||
|               menuLevel2Name: res.data.menuLevel2Name | ||||
|             } | ||||
|             this.fuzzyQueryFields = res.data.fuzzyQueryFields | ||||
|             this.tableInfos = res.data.tableInfos | ||||
|             this.showListFields = res.data.showListFields | ||||
|             this.orderFields = res.data.orderFields | ||||
|             this.btns = Object.keys(res.data).filter(v => { | ||||
|               return this.btnKeys.indexOf(v) > -1 && res.data[v] === '1' | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       submit (info) { | ||||
|         this.instance.post(`/app/appapplicationinfo/addOrUpdate`, { | ||||
|           ...this.info, | ||||
|           ...this.basicInfo, | ||||
|           tableInfos: this.tableInfos, | ||||
|           ...info.btns, | ||||
|           id: this.params.id, | ||||
|           applicationName: this.basicInfo.menuLevel2Lable, | ||||
|           fuzzyQueryFields: info.fuzzyQueryFields, | ||||
|           orderType: info.orderType, | ||||
|           orderFields: info.orderFields, | ||||
|           showListFields: info.showListFields | ||||
|         }).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.$message.success(this.params.id ? '编辑成功' : '添加成功') | ||||
|             this.cancel(true) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       next () { | ||||
|         if (this.currIndex === 0) { | ||||
|           if (!this.$refs.basicInfo.validate()) return | ||||
|         } | ||||
|  | ||||
|         if (this.currIndex === 1) { | ||||
|           this.$refs.form.onConfirm() | ||||
|         } | ||||
|  | ||||
|         if (this.currIndex === 2) { | ||||
|           const info = this.$refs.config.validate() | ||||
|           if (!info) return | ||||
|  | ||||
|           this.submit(info) | ||||
|  | ||||
|           return false | ||||
|         } | ||||
|  | ||||
|         this.currIndex = this.currIndex + 1 | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .form-add { | ||||
|     &.form-add__active { | ||||
|       ::v-deep .ai-detail__content--wrapper { | ||||
|         max-width: 100%!important; | ||||
|         height: 100%!important; | ||||
|         background: #F5F6F9; | ||||
|       } | ||||
|  | ||||
|       .form-config__wrapper { | ||||
|         height: calc(100% - 52px); | ||||
|         overflow-y: hidden; | ||||
|       } | ||||
|  | ||||
|       ::v-deep .ai-detail__content { | ||||
|         height: calc(100% - 114px)!important; | ||||
|         padding: 0!important; | ||||
|         overflow: hidden!important; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .ai-step { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: center; | ||||
|       margin-top: 4px; | ||||
|       margin-bottom: 24px; | ||||
|  | ||||
|       .ai-step__item { | ||||
|         display: flex; | ||||
|         position: relative; | ||||
|         align-items: center; | ||||
|         margin-right: 216px; | ||||
|  | ||||
|         &.ai-step__item--active { | ||||
|           span { | ||||
|             color: #2266FF; | ||||
|           } | ||||
|  | ||||
|           .ai-step__item--icon { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|             border-color: #2266FF; | ||||
|  | ||||
|             i { | ||||
|               width: 12px; | ||||
|               height: 12px; | ||||
|               border-radius: 50%; | ||||
|               background: #2266FF; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         &:after { | ||||
|           position: absolute; | ||||
|           top: 50%; | ||||
|           right: -208px; | ||||
|           width: 200px; | ||||
|           height: 2px; | ||||
|           background: #D0D4DC; | ||||
|           content: ' '; | ||||
|           transform: translateY(-50%); | ||||
|         } | ||||
|  | ||||
|         &:last-child { | ||||
|           margin-right: 0; | ||||
|  | ||||
|           &::after { | ||||
|             display: none; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .ai-step__item--icon { | ||||
|           width: 24px; | ||||
|           height: 24px; | ||||
|           margin-right: 8px; | ||||
|           border-radius: 50%; | ||||
|           background: #FFFFFF; | ||||
|           border: 2px solid #D0D4DC; | ||||
|         } | ||||
|  | ||||
|         .el-icon-success { | ||||
|           width: 24px; | ||||
|           height: 24px; | ||||
|           font-size: 24px; | ||||
|           margin-right: 8px; | ||||
|           color: #2266FF; | ||||
|           border-radius: 50%; | ||||
|         } | ||||
|  | ||||
|         span { | ||||
|           color: #666666; | ||||
|           font-size: 14px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										105
									
								
								packages/2.0.5/AppForm/components/BasicInfo.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								packages/2.0.5/AppForm/components/BasicInfo.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| <template> | ||||
|   <div class="basicInfo"> | ||||
|     <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|       <ai-card title="基本信息"> | ||||
|         <template #content> | ||||
|           <div class="ai-form"> | ||||
|             <el-form-item label="所属平台" prop="saasPlatformId" style="width: 100%;" :rules="[{ required: false, message: '请选择所属平台', trigger: 'change' }]"> | ||||
|               <el-select | ||||
|                 size="small" | ||||
|                 style="width: 100%;" | ||||
|                 placeholder="请选择所属平台" | ||||
|                 clearable | ||||
|                 @change="onChange" | ||||
|                 v-model="form.saasPlatformId"> | ||||
|                 <el-option | ||||
|                   v-for="(item, index) in sassList" | ||||
|                   :key="index" | ||||
|                   :label="item.name" | ||||
|                   :value="item.id"> | ||||
|                 </el-option> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item  style="width: 100%;" label="一级菜单名称" prop="menuLevel1Name" :rules="[{ required: true, message: '请输入一级菜单名称', trigger: 'change' }]"> | ||||
|               <el-input size="small" placeholder="请输入一级菜单名称" :maxlength="8" v-model="form.menuLevel1Name"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%;" label="二级菜单名称" prop="menuLevel2Lable" :rules="[{ required: true, message: '请输入二级菜单名称', trigger: 'change' }]"> | ||||
|               <el-input size="small" placeholder="请输入二级菜单名称" :maxlength="8" v-model="form.menuLevel2Lable"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%;" label="权限列表名称" prop="menuLevel2Name" :rules="[{ required: true, message: '请输入权限列表名称', trigger: 'change' }]"> | ||||
|               <el-input size="small" placeholder="请输入权限列表名称" :maxlength="8" v-model="form.menuLevel2Name"></el-input> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|     </el-form> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'basicInfo', | ||||
|  | ||||
|     model: { | ||||
|       prop: 'value', | ||||
|       event: 'change', | ||||
|     }, | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       value: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         form: { | ||||
|           saasPlatformId: '', | ||||
|           menuLeve1Style: '', | ||||
|           saasPlatformName: '', | ||||
|           menuLevel1Name: '', | ||||
|           menuLevel2Lable: '', | ||||
|           menuLevel2Name: '' | ||||
|         }, | ||||
|         sassList: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     watch: { | ||||
|       value (v) { | ||||
|         this.form = JSON.parse(JSON.stringify(v)) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.getSassList() | ||||
|       this.form = JSON.parse(JSON.stringify(this.value)) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onChange (e) { | ||||
|         this.form.saasPlatformName = this.sassList.filter(v => v.id === e)[0].name | ||||
|       }, | ||||
|  | ||||
|       validate () { | ||||
|         let result = false | ||||
|         this.$refs.form.validate(valid => { | ||||
|           result = valid | ||||
|         }) | ||||
|         this.$emit('change', this.form) | ||||
|         return result  | ||||
|       }, | ||||
|  | ||||
|       getSassList () { | ||||
|         this.instance.post(`/app/appSaas/listAll`).then(res => { | ||||
|           if (res.data) { | ||||
|             this.sassList = res.data | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| </style> | ||||
							
								
								
									
										244
									
								
								packages/2.0.5/AppForm/components/FormConfig.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								packages/2.0.5/AppForm/components/FormConfig.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,244 @@ | ||||
| <template> | ||||
|   <div class="basicInfo"> | ||||
|     <ai-card title="搜索字段" class="search-wrapper"> | ||||
|       <template #content> | ||||
|         <el-checkbox-group v-model="queryFields"> | ||||
|           <el-checkbox | ||||
|             :label="`${item.fieldDbName}~${item.fieldName}`" | ||||
|             v-for="(item, index) in tableInfos" | ||||
|             :key="index"> | ||||
|             {{ item.fieldName }} | ||||
|           </el-checkbox> | ||||
|         </el-checkbox-group> | ||||
|       </template> | ||||
|     </ai-card> | ||||
|     <ai-card title="表格字段"> | ||||
|       <template #content> | ||||
|         <div class="ai-table"> | ||||
|           <div class="el-table el-table--border ai-header__border"> | ||||
|             <el-scrollbar> | ||||
|               <table cellspacing="0" cellpadding="0" border="0" class="el-table__body"> | ||||
|                 <draggable element="thead" animation="500" class="el-table__header is-leaf ai-table__header" :sort="true" v-model="showFields"> | ||||
|                   <th v-for="(item, index) in showFields" style="background: #f3f4f5; text-align: center;" class="ai-table__header" :key="index">{{ item.fieldName }}</th> | ||||
|                 </draggable>  | ||||
|                 <tbody element="tbody"> | ||||
|                   <tr> | ||||
|                     <td @click="handleShow(index, item.isShow)" v-for="(item, index) in showFields" :key="index">{{ item.isShow ? '已显示' : '已隐藏' }}</td> | ||||
|                   </tr> | ||||
|                 </tbody>  | ||||
|               </table> | ||||
|             </el-scrollbar> | ||||
|           </div> | ||||
|         </div> | ||||
|       </template> | ||||
|     </ai-card> | ||||
|     <ai-card title="排序和操作按钮"> | ||||
|       <template #content> | ||||
|         <el-form ref="form" class="ai-form" :model="form" label-width="110px" label-position="right"> | ||||
|           <el-form-item label="排序字段" prop="field"> | ||||
|             <el-select | ||||
|               size="small" | ||||
|               placeholder="默认按创建时间排序" | ||||
|               clearable | ||||
|               v-model="form.field"> | ||||
|               <el-option | ||||
|                 v-for="(filed, index) in tableInfos" | ||||
|                 :key="index" | ||||
|                 :label="filed.fieldName" | ||||
|                 :value="`${filed.fieldDbName}~${filed.fieldName}`"> | ||||
|               </el-option> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="排序类型" prop="orderType" :rules="[{ required: true, message: '请输入排序类型', trigger: 'change' }]"> | ||||
|             <el-radio-group v-model="form.orderType"> | ||||
|               <el-radio label="asc">升序</el-radio> | ||||
|               <el-radio label="desc">降序</el-radio> | ||||
|             </el-radio-group> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="按钮配置" prop="btns" style="width: 100%;" :rules="[{ required: true, message: '请输入按钮配置', trigger: 'change' }]"> | ||||
|             <el-checkbox-group v-model="form.btns"> | ||||
|               <el-checkbox label="insertEnable">添加</el-checkbox> | ||||
|               <el-checkbox label="importEnable">导入</el-checkbox> | ||||
|               <el-checkbox label="exportEnalbe">导出</el-checkbox> | ||||
|               <el-checkbox label="editEnable">编辑</el-checkbox> | ||||
|               <el-checkbox label="deleteEnable">删除</el-checkbox> | ||||
|               <el-checkbox label="batchDelEnable">批量删除</el-checkbox> | ||||
|             </el-checkbox-group> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </template> | ||||
|     </ai-card> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import draggable from 'vuedraggable' | ||||
|   export default { | ||||
|     name: 'configForm', | ||||
|  | ||||
|     props: { | ||||
|       tableInfos: Array, | ||||
|       btns: Array, | ||||
|       showListFields: Array, | ||||
|       orderFields: Array, | ||||
|       fuzzyQueryFields: Array | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       draggable | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         queryFields: [], | ||||
|         tableData: [{}], | ||||
|         btnKeys: ['insertEnable', 'importEnable', 'exportEnalbe', 'editEnable', 'deleteEnable', 'batchDelEnable'], | ||||
|         form: { | ||||
|           btns: [], | ||||
|           orderType: 'asc', | ||||
|           field: '' | ||||
|         }, | ||||
|         showFields: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       const showIds = this.showListFields.map(v => v.fieldDbName) | ||||
|       this.showFields = JSON.parse(JSON.stringify(this.tableInfos)).map(item => { | ||||
|         item.isShow = showIds.indexOf(item.fieldDbName) > -1 ? true : false | ||||
|  | ||||
|         return item | ||||
|       }) | ||||
|  | ||||
|       if (!this.showListFields.length) { | ||||
|         this.showFields.map(v => { | ||||
|           v.isShow = true | ||||
|           return v | ||||
|         }) | ||||
|       } | ||||
|  | ||||
|       this.tableInfos.map(item => { | ||||
|         this.tableData[0][item.fieldDbName] = '删除' | ||||
|       }) | ||||
|  | ||||
|       if (this.btns.length) { | ||||
|         this.form.btns = this.btns | ||||
|       } | ||||
|  | ||||
|       const tableInfosIds = this.tableInfos.map(v => v.fieldDbName) | ||||
|  | ||||
|       if (this.orderFields.length) { | ||||
|         let arr = this.orderFields.filter(v => { | ||||
|           return tableInfosIds.indexOf(v.fieldDbName) > -1 | ||||
|         }).map(item => { | ||||
|           return `${item.fieldDbName}~${item.fieldName}` | ||||
|         }) | ||||
|  | ||||
|         if (arr.length) { | ||||
|           this.form.field = arr[0] | ||||
|         } | ||||
|       } | ||||
|       if (this.fuzzyQueryFields.length) { | ||||
|         this.queryFields = this.fuzzyQueryFields.filter(v => { | ||||
|           return tableInfosIds.indexOf(v.fieldDbName) > -1 | ||||
|         }).map(item => { | ||||
|           return `${item.fieldDbName}~${item.fieldName}` | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       validate () { | ||||
|         let result = false | ||||
|         this.$refs.form.validate(valid => { | ||||
|           result = valid | ||||
|         }) | ||||
|  | ||||
|         if (!result) { | ||||
|           return false | ||||
|         } | ||||
|  | ||||
|         const btns = {} | ||||
|         this.btnKeys.forEach(item => { | ||||
|           btns[item] = this.form.btns.indexOf(item) > -1 ? 1 : 0  | ||||
|         }) | ||||
|  | ||||
|         return { | ||||
|           btns, | ||||
|           orderFields: [{ | ||||
|             fieldName: this.form.field.split('~')[1], | ||||
|             fieldDbName: this.form.field.split('~')[0], | ||||
|             orderType: this.form.orderType | ||||
|           }], | ||||
|           showListFields: this.showFields.filter(v => v.isShow).map((v, index) => { | ||||
|             return { | ||||
|               fieldName: v.fieldName, | ||||
|               fieldDbName: v.fieldDbName, | ||||
|               showListIndex: index | ||||
|             } | ||||
|           }), | ||||
|           fuzzyQueryFields: this.queryFields.map(v => { | ||||
|             return { | ||||
|               fieldName: v.split('~')[1], | ||||
|               fieldDbName: v.split('~')[0] | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       handleShow (index, isShow) { | ||||
|         const total = this.showFields.map(v => v.isShow).filter(v => !!v) | ||||
|         if (total.length <= 1 && isShow) { | ||||
|           return this.$message.error('表格列数不能小于1') | ||||
|         } | ||||
|  | ||||
|         this.$set(this.showFields[index], 'isShow', !isShow) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .basicInfo { | ||||
|     .search-wrapper { | ||||
|       ::v-deep .el-checkbox-group { | ||||
|         display: flex; | ||||
|         flex-wrap: wrap; | ||||
|  | ||||
|         .el-checkbox { | ||||
|           width: 16.66%; | ||||
|           margin-bottom: 10px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .ai-table { | ||||
|     .el-table--border { | ||||
|       border: 1px solid #d0d4dc; | ||||
|       border-bottom: none; | ||||
|       border-right: none; | ||||
|     } | ||||
|     table { | ||||
|       min-width: 100%; | ||||
|     } | ||||
|  | ||||
|     th, tr { | ||||
|       min-width: 100px; | ||||
|       cursor: move; | ||||
|     } | ||||
|  | ||||
|     tr { | ||||
|       td { | ||||
|         cursor: pointer; | ||||
|         color: #26f; | ||||
|         text-align: center; | ||||
|         user-select: none; | ||||
|  | ||||
|         &:hover { | ||||
|           opacity: 0.7; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										1127
									
								
								packages/2.0.5/AppForm/components/FormLayout.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1127
									
								
								packages/2.0.5/AppForm/components/FormLayout.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										182
									
								
								packages/2.0.5/AppForm/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								packages/2.0.5/AppForm/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,182 @@ | ||||
| <template> | ||||
|   <ai-list class="appform"> | ||||
|     <template slot="title"> | ||||
|       <ai-title title="表单配置" isShowBottomBorder></ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar class="search-bar"> | ||||
|         <template #left> | ||||
|           <el-button size="small" type="primary" icon="iconfont iconAdd" @click="toAdd('')">添加</el-button> | ||||
|         </template> | ||||
|         <template slot="right"> | ||||
|           <el-input | ||||
|             v-model="search.applicationName" | ||||
|             size="small" | ||||
|             @keyup.enter.native="search.current = 1, getList()" | ||||
|             placeholder="请输入菜单名称" | ||||
|             clearable | ||||
|             @clear="search.current = 1, search.applicationName = '', getList()" | ||||
|             suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table | ||||
|         :tableData="tableData" | ||||
|         :col-configs="colConfigs" | ||||
|         :total="total" | ||||
|         v-loading="loading" | ||||
|         style="margin-top: 6px;" | ||||
|         :current.sync="search.current" | ||||
|         :size.sync="search.size" | ||||
|         @getList="getList"> | ||||
|         <el-table-column slot="options" width="180px" fixed="right" label="操作" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-options"> | ||||
|               <el-button type="text" @click="push(row.id)" v-if="row.pushStatus === '0'">推送</el-button> | ||||
|               <el-button type="text" @click="operate(row.id, row.status)">{{ row.status === '1' ? '停用' : '启用' }}</el-button> | ||||
|               <el-button type="text" @click="toAdd(row.id)">编辑</el-button> | ||||
|               <el-button type="text" @click="remove(row.id)">删除</el-button> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import { mapState } from 'vuex' | ||||
|   export default { | ||||
|     name: 'List', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|  | ||||
|     data() { | ||||
|       return { | ||||
|         search: { | ||||
|           current: 1, | ||||
|           size: 10, | ||||
|           applicationName: '' | ||||
|         }, | ||||
|         loading: false, | ||||
|         total: 10, | ||||
|         colConfigs: [ | ||||
|           { prop: 'saasPlatformName', label: '所属平台' }, | ||||
|           { prop: 'menuLevel1Name', label: '一级菜单名称'}, | ||||
|           { prop: 'menuLevel2Name', label: '权限列表名称'}, | ||||
|           { prop: 'menuLevel2Lable', label: '二级菜单名称'}, | ||||
|           { prop: 'createUserName', label: '编辑人' }, | ||||
|           { prop: 'createTime', label: '编辑时间' }, | ||||
|           { | ||||
|             prop: 'status', | ||||
|             label: '状态', | ||||
|             align: 'center', | ||||
|             render (h, {row}) { | ||||
|               return h('span',{ | ||||
|                 style: { | ||||
|                   color: row.status === '1' ? '#2EA222' : '#F46' | ||||
|                 } | ||||
|               }, row.status === '1' ? '启用' : '停用') | ||||
|             } | ||||
|           }, | ||||
|           { | ||||
|             prop: 'pushStatus', | ||||
|             label: '推送状态', | ||||
|             align: 'center', | ||||
|             render (h, {row}) { | ||||
|               return h('span',{ | ||||
|                 style: { | ||||
|                   color: row.pushStatus === '1' ? '#2EA222' : '#F46' | ||||
|                 } | ||||
|               }, row.pushStatus === '1' ? '成功' : '失败') | ||||
|             } | ||||
|           } | ||||
|         ], | ||||
|         tableData: [], | ||||
|         ids: '' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       ...mapState(['user']) | ||||
|     }, | ||||
|  | ||||
|     mounted() { | ||||
|       this.getList() | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.loading = true | ||||
|         this.instance.post(`/app/appapplicationinfo/list`, null, { | ||||
|           params: { | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|  | ||||
|             this.$nextTick(() => { | ||||
|               this.loading = false | ||||
|             }) | ||||
|           } else { | ||||
|             this.loading = false | ||||
|           } | ||||
|         }).catch(() => { | ||||
|           this.loading = false | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       removeAll () { | ||||
|         if (!this.ids) return | ||||
|  | ||||
|         this.remove(this.ids) | ||||
|       }, | ||||
|  | ||||
|       push (id) { | ||||
|         this.instance.post(`/app/appapplicationinfo/push?id=${id}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success(`推送成功`) | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       operate (id, status) { | ||||
|         this.instance.post(`/app/appapplicationinfo/enable?id=${id}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success(`${status === '1' ? '停用成功' : '启用成功'}`) | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       remove (id) { | ||||
|         this.$confirm('确定删除该数据?').then(() => { | ||||
|           this.instance.post(`/app/appapplicationinfo/delete?ids=${id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       toAdd(id) { | ||||
|         this.$emit('change', { | ||||
|           type: 'Add', | ||||
|           params: { | ||||
|             id: id || '' | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| </style> | ||||
							
								
								
									
										272
									
								
								packages/2.0.5/AppForm/components/config.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								packages/2.0.5/AppForm/components/config.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,272 @@ | ||||
| export const components = [ | ||||
| 	{ | ||||
| 		type: 'info', | ||||
| 		tips: '(不能重复添加同一元素)', | ||||
| 		label: '信息', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'name', | ||||
| 				fieldName: '姓名', | ||||
| 				fieldTips: '请输入姓名', | ||||
| 				fixedLabel: '姓名', | ||||
| 				disable: '0', | ||||
| 				grid: 0.5, | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_box', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 20 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'idNumber', | ||||
| 				fieldName: '身份证号', | ||||
| 				fixedLabel: '身份证号', | ||||
| 				fieldTips: '请输入身份证号', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 20, | ||||
| 				disable: '0', | ||||
| 				grid: 0.5 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'phone', | ||||
| 				fieldName: '联系方式', | ||||
| 				fixedLabel: '联系方式', | ||||
| 				fieldTips: '请输入联系方式', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 20, | ||||
| 				disable: '0', | ||||
| 				grid: 0.5 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'area', | ||||
| 				fieldName: '地区', | ||||
| 				fixedLabel: '地区', | ||||
| 				fieldTips: '请选择地区', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				areaPattern: '', | ||||
| 				disable: '0', | ||||
| 				grid: 0.5 | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	{ | ||||
| 		type: 'options', | ||||
| 		tips: '(可重复添加)', | ||||
| 		label: '选项', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'radio', | ||||
| 				fieldName: '单选', | ||||
| 				fixedLabel: '单选', | ||||
| 				fieldTips: '请选择', | ||||
| 				grid: 0.5, | ||||
| 				icon: 'iconradio', | ||||
| 				mustFill: '1', | ||||
| 				disable: '0', | ||||
| 				defaultValue: '', | ||||
| 				options: [ | ||||
| 					{ | ||||
| 						label: '选项1', | ||||
| 						value: '' | ||||
| 					}, | ||||
| 					{ | ||||
| 						label: '选项2', | ||||
| 						value: '' | ||||
| 					} | ||||
| 				], | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'checkbox', | ||||
| 				fieldName: '多选', | ||||
| 				fixedLabel: '多选', | ||||
| 				fieldTips: '请选择', | ||||
| 				icon: 'iconcheck_box', | ||||
| 				mustFill: '1', | ||||
| 				grid: 0.5, | ||||
| 				disable: '0', | ||||
| 				defaultValue: [], | ||||
| 				options: [ | ||||
| 					{ | ||||
| 						label: '选项1', | ||||
| 						value: '' | ||||
| 					}, | ||||
| 					{ | ||||
| 						label: '选项2', | ||||
| 						value: '' | ||||
| 					} | ||||
| 				], | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'select', | ||||
| 				fieldName: '单下拉框', | ||||
| 				fixedLabel: '单下拉框', | ||||
| 				grid: 0.5, | ||||
| 				fieldTips: '请选择', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				defaultValue: '', | ||||
| 				disable: '0', | ||||
| 				options: [ | ||||
| 					{ | ||||
| 						label: '选项1', | ||||
| 						value: '' | ||||
| 					}, | ||||
| 					{ | ||||
| 						label: '选项2', | ||||
| 						value: '' | ||||
| 					} | ||||
| 				], | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'onOff', | ||||
| 				fieldName: '开关', | ||||
| 				fixedLabel: '开关', | ||||
| 				grid: 0.5, | ||||
| 				fieldTips: '请选择开关', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				defaultValue: '0', | ||||
| 				disable: '0', | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'date', | ||||
| 				fieldName: '日期', | ||||
| 				fixedLabel: '日期', | ||||
| 				grid: 0.5, | ||||
| 				datetimePattern: 'yyyy-MM-dd', | ||||
| 				fieldTips: '请选择日期', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				disable: '0', | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'time', | ||||
| 				fieldName: '时间', | ||||
| 				fixedLabel: '时间', | ||||
| 				grid: 0.5, | ||||
| 				datetimePattern: 'HH:mm:ss', | ||||
| 				fieldTips: '请选择时间', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				disable: '0', | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'datetime', | ||||
| 				fieldName: '日期时间', | ||||
| 				fixedLabel: '日期时间', | ||||
| 				grid: 0.5, | ||||
| 				datetimePattern: 'yyyy-MM-dd HH:mm:ss', | ||||
| 				fieldTips: '请选择日期时间', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				disable: '0', | ||||
| 				title: '' | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	{ | ||||
| 		type: 'input', | ||||
| 		tips: '(可重复添加)', | ||||
| 		label: '填空', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'input', | ||||
| 				fieldName: '单行填空', | ||||
| 				fieldTips: '请输入', | ||||
| 				fixedLabel: '单行填空', | ||||
| 				disable: '0', | ||||
| 				grid: 0.5, | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_box', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 50 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'textarea', | ||||
| 				fieldName: '多行填空', | ||||
| 				fixedLabel: '多行填空', | ||||
| 				fieldTips: '请输入', | ||||
| 				lineNumber: 4, | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 500, | ||||
| 				disable: '0', | ||||
| 				grid: 1 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'number', | ||||
| 				fieldName: '数字输入', | ||||
| 				fixedLabel: '数字输入', | ||||
| 				fieldTips: '请输入数字', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxValue: 10000, | ||||
| 				decimalPlaces: 0, | ||||
| 				minValue: 0, | ||||
| 				maxLength: 500, | ||||
| 				disable: '0', | ||||
| 				grid: 0.5 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'rtf', | ||||
| 				fieldName: '富文本', | ||||
| 				fixedLabel: '富文本', | ||||
| 				fieldTips: '请输入', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 5000, | ||||
| 				disable: '0', | ||||
| 				grid: 1 | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	{ | ||||
| 		type: 'annex', | ||||
| 		tips: '(可重复添加)', | ||||
| 		label: '附件', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'upload', | ||||
| 				fieldTips: '请上传', | ||||
| 				fieldName: '上传附件', | ||||
| 				fixedLabel: '上传附件', | ||||
| 				disable: '0', | ||||
| 				fileChoseSize: 10, | ||||
| 				fileMaxCount: 9, | ||||
| 				defaultValue: '', | ||||
| 				icon: 'iconpic', | ||||
| 				mustFill: '1', | ||||
| 				grid: 1 | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	{ | ||||
| 		type: 'layout', | ||||
| 		tips: '(可重复添加)', | ||||
| 		label: '分组', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'group', | ||||
| 				fieldName: '卡片', | ||||
| 				fixedLabel: '卡片', | ||||
| 				icon: 'iconpic', | ||||
| 				groupName: '分组标题', | ||||
| 				column: [] | ||||
| 			} | ||||
| 		] | ||||
| 	} | ||||
| ]; | ||||
							
								
								
									
										75
									
								
								packages/2.0.5/AppGridBlock/AppGridBlock.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								packages/2.0.5/AppGridBlock/AppGridBlock.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| <template> | ||||
|   <div class="AppGridBlock"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component | ||||
|         ref="component" | ||||
|         :is="component" | ||||
|         @change="onChange" | ||||
|         :params="params" | ||||
|         :instance="instance" | ||||
|         :dict="dict" | ||||
|         :isEdit="isEdit" | ||||
|       ></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from "./components/list"; | ||||
| import Add from "./components/add"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppGridBlock", | ||||
|   label: "网格区块", | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: "List", | ||||
|       params: {}, | ||||
|       include: [], | ||||
|       isEdit: false | ||||
|     }; | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     Add, | ||||
|     List, | ||||
|   }, | ||||
|  | ||||
|   mounted() {}, | ||||
|  | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === "Add") { | ||||
|         this.component = "Add"; | ||||
|         this.params = data.params; | ||||
|         this.isEdit = data.isEdit | ||||
|       } | ||||
|  | ||||
|       if (data.type === "list") { | ||||
|         this.component = "List"; | ||||
|         this.params = data.params; | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getList(); | ||||
|           } | ||||
|         }); | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppGridBlock { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										566
									
								
								packages/2.0.5/AppGridBlock/components/add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										566
									
								
								packages/2.0.5/AppGridBlock/components/add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,566 @@ | ||||
| <template> | ||||
|   <div class="add-block"> | ||||
|     <ai-detail> | ||||
|       <template #title> | ||||
|         <ai-title | ||||
|           :title="title" | ||||
|           :isShowBack="true" | ||||
|           :isShowBottomBorder="true" | ||||
|           @onBackClick="cancel(false)" | ||||
|         ></ai-title> | ||||
|       </template> | ||||
|       <template #content> | ||||
|         <ai-card title="层级信息" > | ||||
|           <template slot="content"> | ||||
|             <ai-wrapper  label-width="120px" :columnsNumber="2" style="margin-top: 16px"> | ||||
|               <ai-info-item label="上级层级单位:"><span>{{ forms.parentGirdName }}</span></ai-info-item> | ||||
|             </ai-wrapper> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|          | ||||
|         <el-form | ||||
|           ref="rules" | ||||
|           :model="forms" | ||||
|           :rules="formRules" | ||||
|           size="small" | ||||
|           label-suffix=":" | ||||
|           label-width="120px" | ||||
|         > | ||||
|           <ai-card title="基础信息" > | ||||
|             <template slot="content"> | ||||
|               <div class="above"> | ||||
|                 <div class="left"> | ||||
|                   <el-form-item label="网格名称" prop="girdName"> | ||||
|                     <el-input | ||||
|                       v-model="forms.girdName" | ||||
|                       placeholder="请输入…" | ||||
|                       maxlength="10" | ||||
|                       show-word-limit | ||||
|                     ></el-input> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="网格类型" prop="girdType"> | ||||
|                     <el-select | ||||
|                       v-model="forms.girdType" | ||||
|                       placeholder="请选择" | ||||
|                       clearable | ||||
|                     > | ||||
|                       <el-option | ||||
|                         v-for="(item, i) in dict.getDict('girdType')" | ||||
|                         :key="i" | ||||
|                         :label="item.dictName" | ||||
|                         :value="item.dictValue" | ||||
|                       ></el-option> | ||||
|                     </el-select> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="是否最后一级" prop="isLastLevel"> | ||||
|                     <el-select | ||||
|                       v-model="forms.isLastLevel" | ||||
|                       placeholder="请选择" | ||||
|                       :disabled="isEdit" | ||||
|                       clearable | ||||
|                     > | ||||
|                       <el-option | ||||
|                         v-for="(item, i) in dict.getDict('isLastLevel')" | ||||
|                         :key="i" | ||||
|                         :label="item.dictName" | ||||
|                         :value="item.dictValue" | ||||
|                       ></el-option> | ||||
|                     </el-select> | ||||
|                   </el-form-item> | ||||
|                 </div> | ||||
|                 <div class="right"> | ||||
|                   <el-form-item label="网格编码" prop="girdCode"> | ||||
|                     <el-input | ||||
|                       v-model="forms.girdCode" | ||||
|                       placeholder="请输入…" | ||||
|                       maxlength="30" | ||||
|                       show-word-limit | ||||
|                     ></el-input> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="网格层级" prop="girdLevel"> | ||||
|                     <el-select | ||||
|                       v-model="forms.girdLevel" | ||||
|                       placeholder="请选择" | ||||
|                       :disabled="isEdit" | ||||
|                       clearable | ||||
|                     > | ||||
|                       <el-option | ||||
|                         v-for="(item, i) in dict.getDict('girdLevel')" | ||||
|                         :key="i" | ||||
|                         :label="item.dictName" | ||||
|                         :value="item.dictValue" | ||||
|                       ></el-option> | ||||
|                     </el-select> | ||||
|                   </el-form-item> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|  | ||||
|           <ai-card title="其他信息" > | ||||
|             <template slot="content"> | ||||
|               <div class="above"> | ||||
|                 <div class="left"> | ||||
|                   <!-- <el-form-item label="事件上报主体" prop="eventReportUnitId"> | ||||
|                     <el-cascader | ||||
|                       style="width: 100%" | ||||
|                       :options="unitOps" | ||||
|                       ref="cascader" | ||||
|                       v-model="forms.eventReportUnitId" | ||||
|                       :props="unitProps" | ||||
|                       :show-all-levels="false" | ||||
|                     /> | ||||
|                   </el-form-item> --> | ||||
|                   <el-form-item label="初始日期" prop="startDate"> | ||||
|                     <el-date-picker | ||||
|                       v-model="forms.startDate" | ||||
|                       type="date" | ||||
|                       value-format="yyyy-MM-dd" | ||||
|                       placeholder="选择日期" | ||||
|                     > | ||||
|                     </el-date-picker> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="终止日期" prop="endDate"> | ||||
|                     <el-date-picker | ||||
|                       v-model="forms.endDate" | ||||
|                       type="date" | ||||
|                       value-format="yyyy-MM-dd" | ||||
|                       placeholder="选择日期" | ||||
|                     > | ||||
|                     </el-date-picker> | ||||
|                   </el-form-item> | ||||
|                 </div> | ||||
|                 <div class="right"> | ||||
|                   <el-form-item label="面积" prop="area"> | ||||
|                     <el-input | ||||
|                       v-model="forms.area" | ||||
|                       placeholder="面积㎡" | ||||
|                     ></el-input> | ||||
|                   </el-form-item> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <el-form-item label="网格地址" prop="address"> | ||||
|                 <el-input v-model="forms.address" placeholder="限200字" maxlength="200"></el-input> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="网格范围" prop="enclosure"> | ||||
|                 <el-button size="small" @click="showMap = true">地图标绘</el-button> | ||||
|               </el-form-item> | ||||
|             </template> | ||||
|           </ai-card>  | ||||
|         </el-form> | ||||
|       </template> | ||||
|       <template #footer> | ||||
|         <el-button @click="cancel(false)" class="delete-btn footer-btn"> | ||||
|           取 消 | ||||
|         </el-button> | ||||
|         <el-button type="primary" @click="save()" class="footer-btn"> | ||||
|           提 交 | ||||
|         </el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|     <ai-dialog | ||||
|       title="网格范围" | ||||
|       :visible.sync="showMap" | ||||
|       :customFooter="true" | ||||
|       :destroyOnClose="true" | ||||
|       @opened="beforeSelectMap" | ||||
|       border | ||||
|       width="850px" | ||||
|     > | ||||
|       <div class="map"> | ||||
|         <div class="tipinput"> | ||||
|           <el-input | ||||
|             v-model="searchAddress" | ||||
|             @change="addressChange" | ||||
|             clearable | ||||
|             placeholder="请输入关键字" | ||||
|             id="tipinput" | ||||
|             size="medium" | ||||
|             style="width: 200px" | ||||
|           ></el-input> | ||||
|         </div> | ||||
|         <div id="panel"></div> | ||||
|         <div class="container" id="container"></div> | ||||
|         <el-button-group | ||||
|           style="margin-top: 8px" | ||||
|           v-if="forms.plottingStatus == 1" | ||||
|         > | ||||
|           <el-button type="primary" size="mini" @click="polyEditor.open()" | ||||
|             >开始编辑</el-button | ||||
|           > | ||||
|           <el-button size="mini" @click="polyEditor.close()" | ||||
|             >结束编辑</el-button | ||||
|           > | ||||
|         </el-button-group> | ||||
|         <el-button-group | ||||
|           style="margin-top: 8px" | ||||
|           v-if="forms.plottingStatus == 0" | ||||
|         > | ||||
|           <el-button size="mini" @click="draw('polygon')" | ||||
|             >开始绘制多边形</el-button | ||||
|           > | ||||
|           <!-- <el-button  size="mini" @click="close()">关闭绘制</el-button> --> | ||||
|           <el-button size="mini" @click="clear()">清除绘制</el-button> | ||||
|         </el-button-group> | ||||
|       </div> | ||||
|       <div class="dialog-footer" slot="footer"> | ||||
|         <el-button size="medium" @click="showMap = false">取消</el-button> | ||||
|         <el-button type="primary" size="medium" @click="surePotting()" | ||||
|           >确认</el-button | ||||
|         > | ||||
|       </div> | ||||
|     </ai-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AMapLoader from "@amap/amap-jsapi-loader"; | ||||
| import { mapState } from "vuex"; | ||||
| export default { | ||||
|   name: "addBlock", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     isEdit: Boolean | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       forms: { | ||||
|         address: "", | ||||
|         area: "", | ||||
|         points: [], | ||||
|         endDate: "", | ||||
|         eventReportUnit: "", | ||||
|         eventReportUnitId: "", | ||||
|         girdCode: "", | ||||
|         girdLevel: "", | ||||
|         girdList: [], | ||||
|         girdName: "", | ||||
|         girdType: "", | ||||
|         isLastLevel: "", | ||||
|         parentGirdId: "", | ||||
|         parentGirdName: "", | ||||
|         startDate: "", | ||||
|         plottingStatus: "0", | ||||
|       }, | ||||
|       showMap: false, | ||||
|       map: "", | ||||
|       mouseTool: "", | ||||
|       searchAddress: "", | ||||
|       placeSearch: "", | ||||
|       overlays: [], | ||||
|       options: [], | ||||
|       path: [], | ||||
|       polyEditor: "", | ||||
|       title: "添加网格区块", | ||||
|       parentGirdInfo: {}, | ||||
|     }; | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(["user"]), | ||||
|     formRules() { | ||||
|       return { | ||||
|         girdName: [ | ||||
|           { required: true, message: "请填写网格名称", trigger: "change" }, | ||||
|         ], | ||||
|         girdCode: [ | ||||
|           { required: true, message: "请填写网格编码", trigger: "change" }, | ||||
|         ], | ||||
|         girdType: [ | ||||
|           { required: true, message: "请选择网格类型", trigger: "change" }, | ||||
|         ], | ||||
|         isLastLevel: [ | ||||
|           { required: true, message: "请选择是否最后一级", trigger: "change" }, | ||||
|         ], | ||||
|         girdLevel: [ | ||||
|           { required: true, message: "请选择网格层级", trigger: "change" }, | ||||
|         ], | ||||
|         eventReportUnitId: [ | ||||
|           { required: true, message: "请选择事件上报主体", trigger: "change" }, | ||||
|         ], | ||||
|       }; | ||||
|     }, | ||||
|     unitProps() { | ||||
|       return { | ||||
|         value: "id", | ||||
|         checkStrictly: true, | ||||
|         emitPath: false, | ||||
|       }; | ||||
|     }, | ||||
|     unitOps() { | ||||
|       let initData = JSON.parse(JSON.stringify(this.options)), | ||||
|         ops = initData.filter((e) => !e.parentId); | ||||
|       ops.map((e) => this.addChild(e, initData)); | ||||
|       return ops; | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     if (this.isEdit) { | ||||
|       this.title = "编辑网格区块"; | ||||
|       this.searchDetail(); | ||||
|     } else { | ||||
|       this.forms.parentGirdId = this.params.id; | ||||
|       this.forms.parentGirdName = this.params.girdName; | ||||
|       // this.forms.girdLevel = Number(this.info.girdLevel) + 1 +''; | ||||
|       // this.forms.isLastLevel = ['0','1'].includes(this.forms.girdLevel)?'0':'1'; | ||||
|       this.title = "添加网格区块"; | ||||
|     } | ||||
|     this.getAllUnit(this.user.info.areaId); | ||||
|   }, | ||||
|   methods: { | ||||
|     cancel (isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: isRefresh ? true : false, | ||||
|       }) | ||||
|     }, | ||||
|     // 获取所有单位 | ||||
|     getAllUnit(data) { | ||||
|       this.options = []; | ||||
|       this.instance | ||||
|         .post("/admin/sysunit/getAll", null, { | ||||
|           params: { | ||||
|             areaId: data, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           res.data = res.data.map((a) => { | ||||
|             return { ...a, label: a.name }; | ||||
|           }); | ||||
|           this.options = res.data.filter((e) => !e.parentId); | ||||
|           this.options.map((t) => this.addChild(t, res.data)); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     beforeSelectMap() { | ||||
|       AMapLoader.load({ | ||||
|         key: "b553334ba34f7ac3cd09df9bc8b539dc", // 申请好的Web端开发者Key,首次调用 load 时必填 | ||||
|         version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 | ||||
|         plugins: ["AMap.MouseTool", "AMap.PlaceSearch", "AMap.PolygonEditor"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 | ||||
|         AMapUI: { | ||||
|           // 是否加载 AMapUI,缺省不加载 | ||||
|           version: "1.1", // AMapUI 缺省 1.1 | ||||
|           plugins: [], // 需要加载的 AMapUI ui插件 | ||||
|         }, | ||||
|       }) | ||||
|         .then((AMap) => { | ||||
|           this.map = new AMap.Map("container", { | ||||
|             resizeEnable: true, | ||||
|           }); | ||||
|           if (this.forms.plottingStatus == 1) { | ||||
|             let path = []; | ||||
|             this.forms.points.map((e, index) => { | ||||
|               path[index] = [e.lng, e.lat]; | ||||
|             }); | ||||
|             let polygon = new AMap.Polygon({ | ||||
|               path: path, | ||||
|               strokeColor: "#FF33FF", | ||||
|               strokeWeight: 6, | ||||
|               strokeOpacity: 0.2, | ||||
|               fillOpacity: 0.4, | ||||
|               fillColor: "#1791fc", | ||||
|               zIndex: 50, | ||||
|               bubble: true, | ||||
|             }); | ||||
|             this.map.add([polygon]); | ||||
|             this.map.setFitView(); | ||||
|             this.polyEditor = new AMap.PolygonEditor(this.map, polygon); | ||||
|           } else { | ||||
|             this.mouseTool = new AMap.MouseTool(this.map); | ||||
|             // this.map.add(new AMap.Marker({ | ||||
|             //     position:this.map.getCenter() | ||||
|             // })); | ||||
|             this.placeSearch = new AMap.PlaceSearch({ | ||||
|               pageSize: 3, // 单页显示结果条数 | ||||
|               pageIndex: 1, // 页码 | ||||
|               city: "", // 兴趣点城市 | ||||
|               citylimit: false, //是否强制限制在设置的城市内搜索 | ||||
|               map: this.map, // 展现结果的地图实例 | ||||
|               panel: "panel", // 结果列表将在此容器中进行展示。 | ||||
|               autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围 | ||||
|             }); | ||||
|             this.map.setZoomAndCenter(14, [117.147097, 36.72081], false, 600); | ||||
|             this.eventOn(); | ||||
|           } | ||||
|         }) | ||||
|         .catch((e) => { | ||||
|           console.log(e); | ||||
|         }); | ||||
|     }, | ||||
|     //地图事件绑定 | ||||
|     eventOn() { | ||||
|       this.path = []; | ||||
|       this.overlays = []; | ||||
|       this.map.on("mousemove", this.showInfoMove, this); | ||||
|       this.mouseTool.on("draw", ({ type, obj }) => { | ||||
|         console.log(obj); | ||||
|         obj.getPath().map((e) => { | ||||
|           this.path.push({ lat: e.getLat(), lng: e.getLng() }); | ||||
|         }); | ||||
|         this.overlays.push(obj); | ||||
|       }); | ||||
|       this.placeSearch.on("listElementClick", (e) => { | ||||
|         console.log(e); | ||||
|       }); | ||||
|     }, | ||||
|     //map搜索 | ||||
|     addressChange(val) { | ||||
|       this.placeSearch.search(val); | ||||
|     }, | ||||
|     close() { | ||||
|       this.mouseTool.close(true); | ||||
|     }, | ||||
|     clear() { | ||||
|       this.map.remove(this.overlays); | ||||
|       this.overlays = []; | ||||
|       this.path = []; | ||||
|     }, | ||||
|     draw(type) { | ||||
|       switch (type) { | ||||
|         case "marker": { | ||||
|           this.mouseTool.marker({ | ||||
|             //同Marker的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|         case "polyline": { | ||||
|           this.mouseTool.polyline({ | ||||
|             strokeColor: "#80d8ff", | ||||
|             //同Polyline的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|         case "polygon": { | ||||
|           this.mouseTool.polygon({ | ||||
|             fillColor: "#00b0ff", | ||||
|             strokeColor: "#80d8ff", | ||||
|             borderWeight: 2, | ||||
|             strokeWeight: 4, | ||||
|             //同Polygon的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|         case "rectangle": { | ||||
|           this.mouseTool.rectangle({ | ||||
|             fillColor: "#00b0ff", | ||||
|             strokeColor: "#80d8ff", | ||||
|             //同Polygon的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|         case "circle": { | ||||
|           this.mouseTool.circle({ | ||||
|             fillColor: "#00b0ff", | ||||
|             strokeColor: "#80d8ff", | ||||
|             //同Circle的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     surePotting() { | ||||
|       this.forms.points = []; | ||||
|       // this.forms.eventReportUnit = this.$refs.cascader.getCheckedNodes().label; | ||||
|       if (this.forms.plottingStatus == 1) { | ||||
|         this.polyEditor | ||||
|           .getTarget() | ||||
|           .getPath() | ||||
|           .map((e) => { | ||||
|             this.forms.points.push({ lng: e.lng, lat: e.lat }); | ||||
|           }); | ||||
|       } else { | ||||
|         this.forms.points = [...this.path]; | ||||
|       } | ||||
|       this.showMap = false; | ||||
|     }, | ||||
|     save() { | ||||
|       this.$refs["rules"].validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.instance | ||||
|             .post( | ||||
|               `/app/appgirdinfo/addOrUpdate`, | ||||
|               { | ||||
|                 ...this.forms, | ||||
|               }, | ||||
|               null | ||||
|             ) | ||||
|             .then((res) => { | ||||
|               if (res.code == 0) { | ||||
|                 this.cancel(true) | ||||
|               } | ||||
|             }); | ||||
|         } else { | ||||
|           console.log("error submit!!"); | ||||
|           return false; | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     searchDetail() { | ||||
|       this.instance | ||||
|         .post(`/app/appgirdinfo/queryDetailById`, null, { | ||||
|           params: { id: this.params.id }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.forms = { ...res.data }; | ||||
|             this.parentGirdInfo = this.forms.parentGirdInfo; | ||||
|             this.forms.parentGirdName = this.parentGirdInfo.girdName; | ||||
|             // this.forms.isLastLevel =this.forms.girdLevel; | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .add-block { | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   .above { | ||||
|     overflow: hidden; | ||||
|     padding: 8px 0; | ||||
|     .left { | ||||
|       width: 380px; | ||||
|       float: left; | ||||
|     } | ||||
|     .right { | ||||
|       width: 380px; | ||||
|       float: right; | ||||
|     } | ||||
|   } | ||||
|   .footer-btn { | ||||
|     width: 92px; | ||||
|   } | ||||
|   .map { | ||||
|     width: 780px; | ||||
|     position: relative; | ||||
|     overflow: hidden; | ||||
|     .container { | ||||
|       width: 760px; | ||||
|       height: 420px; | ||||
|       border-radius: 2px; | ||||
|       border: 1px solid #d0d4dc; | ||||
|     } | ||||
|     #panel { | ||||
|       position: absolute; | ||||
|       height: 400px; | ||||
|       right: 30px; | ||||
|       overflow-x: auto; | ||||
|       top: 20px; | ||||
|       width: 280px; | ||||
|       overflow: hidden; | ||||
|       z-index: 10000; | ||||
|     } | ||||
|     .tipinput { | ||||
|       position: absolute; | ||||
|       width: 200px; | ||||
|       height: 38px; | ||||
|       left: 20px; | ||||
|       top: 20px; | ||||
|       z-index: 10000; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										676
									
								
								packages/2.0.5/AppGridBlock/components/list.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										676
									
								
								packages/2.0.5/AppGridBlock/components/list.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,676 @@ | ||||
| <template> | ||||
|   <div class="app-grid-block"> | ||||
|     <ai-list> | ||||
|       <template slot="title"> | ||||
|         <ai-title title="网格区块" :isShowBottomBorder="true"></ai-title> | ||||
|       </template> | ||||
|       <template slot="left"> | ||||
|         <ai-tree-menu title="网格层级" @search="(v) => $refs.tree.filter(v)"> | ||||
|           <el-tree | ||||
|             :data="treeObj.treeList" | ||||
|             :props="treeObj.defaultProps" | ||||
|             @node-click="handleNodeClick" | ||||
|             node-key="id" | ||||
|             ref="tree" | ||||
|             :filter-node-method="filterNode" | ||||
|             default-expand-all | ||||
|             highlight-current | ||||
|           /> | ||||
|           <footer> | ||||
|             <span | ||||
|               class="iconfont iconAdd" | ||||
|               title="添加二级网格" | ||||
|               @click="(isEdit = false), addTwoLevel()" | ||||
|             /> | ||||
|             <el-button | ||||
|               icon="iconfont iconEdit" | ||||
|               title="编辑二级网格" | ||||
|               type="text" | ||||
|               :disabled="info.girdLevel != '1'" | ||||
|               @click="(isEdit = true), toAdd()" | ||||
|             /> | ||||
|             <span class="iconfont iconDelete" @click="deleteTree(info.id)" /> | ||||
|           </footer> | ||||
|         </ai-tree-menu> | ||||
|       </template> | ||||
|       <template slot="content"> | ||||
|         <ai-search-bar> | ||||
|           <template slot="left"> | ||||
|             <el-date-picker | ||||
|               v-model="searchObj.createTimeStr" | ||||
|               type="date" | ||||
|               @change="(page.current = 1), getList()" | ||||
|               value-format="yyyy-MM-dd" | ||||
|               size="small" | ||||
|               placeholder="创建时间" | ||||
|             > | ||||
|             </el-date-picker> | ||||
|           </template> | ||||
|           <template slot="right"> | ||||
|             <el-input | ||||
|               v-model="searchObj.girdName" | ||||
|               size="small" | ||||
|               placeholder="输入网格名称" | ||||
|               @keyup.enter.native="(page.current = 1), getList()" | ||||
|               clearable | ||||
|               prefix-icon="iconfont iconSearch" | ||||
|             /> | ||||
|             <el-button | ||||
|               type="primary" | ||||
|               icon="iconfont iconSearch" | ||||
|               size="small" | ||||
|               @click="(page.current = 1), getList()" | ||||
|               >查询 | ||||
|             </el-button> | ||||
|             <el-button | ||||
|               icon="el-icon-refresh-right" | ||||
|               size="small" | ||||
|               @click="resetSearch" | ||||
|               >重置</el-button | ||||
|             > | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-search-bar bottomBorder> | ||||
|           <template slot="left"> | ||||
|             <el-button | ||||
|               type="primary" | ||||
|               icon="iconfont iconAdd" | ||||
|               :disabled="info.girdLevel != '1'" | ||||
|               @click="(isEdit = false), toAdd()" | ||||
|               >新增 | ||||
|             </el-button> | ||||
|             <el-button | ||||
|               icon="iconfont iconDelete" | ||||
|               @click="deleteById(ids.join(','))" | ||||
|               :disabled="!Boolean(ids.length)" | ||||
|             > | ||||
|               删除 | ||||
|             </el-button> | ||||
|             <ai-download | ||||
|               :instance="instance" | ||||
|               url="/app/appgirdinfo/exportGirdInfo" | ||||
|               :params="{ ...searchObj, ids: ids.join(',') }" | ||||
|               fileName="网格区块" | ||||
|             > | ||||
|               <el-button icon="iconfont iconExported" size="small" | ||||
|                 >导出全部</el-button | ||||
|               > | ||||
|             </ai-download> | ||||
|             <ai-import | ||||
|               ref="import" | ||||
|               title="导入" | ||||
|               name="网格区块" | ||||
|               url="/app/appgirdinfo/downloadGirdInfo" | ||||
|               importUrl="/app/appgirdinfo/importGirdInfo" | ||||
|               suffixName="xlsx" | ||||
|               :customCliker="true" | ||||
|               :instance="instance" | ||||
|             > | ||||
|               <template slot="tips"> | ||||
|                 <p> | ||||
|                   如果表格中已经存在数据,则会被本次导入的数据覆盖;不存在数据,系统将生成新的标准记录; | ||||
|                 </p> | ||||
|               </template> | ||||
|               <el-button size="small" icon="iconfont iconImport" | ||||
|                 >导入</el-button | ||||
|               > | ||||
|             </ai-import> | ||||
|           </template> | ||||
|           <!-- <template slot="right"> | ||||
|               <el-input placeholder="输入网格名称" size="small" v-model="searchObj.con" | ||||
|            @keyup.enter.native="page.current=1,getList()" prefix-icon="iconfont iconSearch"/> | ||||
|              <el-button type="primary" icon="iconfont iconSearch" size="small" | ||||
|                      @click="page.current=1,getList()">查询 | ||||
|              </el-button> | ||||
|              <el-button icon="el-icon-refresh-right" size="small" @click="resetSearch">重置</el-button> | ||||
|           </template> --> | ||||
|         </ai-search-bar> | ||||
|         <ai-table | ||||
|           class="mt10" | ||||
|           :tableData="tableData" | ||||
|           :col-configs="colConfigs" | ||||
|           :total="page.total" | ||||
|           ref="aitableex" | ||||
|           :current.sync="page.current" | ||||
|           :size.sync="page.size" | ||||
|           @selection-change="(v) => (ids = v.map((e) => e.id))" | ||||
|           @getList="getList()" | ||||
|         > | ||||
|           <el-table-column | ||||
|             slot="selectId" | ||||
|             type="selection" | ||||
|             align="center" | ||||
|             width="40" | ||||
|           > | ||||
|           </el-table-column> | ||||
|           <el-table-column | ||||
|             label="操作" | ||||
|             slot="options" | ||||
|             align="center" | ||||
|             fixed="right" | ||||
|             width="250" | ||||
|           > | ||||
|             <template v-slot="{ row }"> | ||||
|               <el-button type="text" @click="see(row)">编辑</el-button> | ||||
|               <el-button type="text" @click="poltting(row)">标绘</el-button> | ||||
|               <el-button type="text" @click="deleteById(row.id)" | ||||
|                 >删除</el-button | ||||
|               > | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <ai-dialog | ||||
|       title="网格范围" | ||||
|       :visible.sync="showMap" | ||||
|       :customFooter="true" | ||||
|       :destroyOnClose="true" | ||||
|       border | ||||
|       width="850px" | ||||
|     > | ||||
|       <div class="map"> | ||||
|         <div class="tipinput"> | ||||
|           <el-input | ||||
|             v-if="editRow.plottingStatus == 0" | ||||
|             v-model="searchAddress" | ||||
|             @change="addressChange" | ||||
|             clearable | ||||
|             placeholder="请输入关键字" | ||||
|             id="tipinput" | ||||
|             size="medium" | ||||
|             style="width: 200px" | ||||
|           ></el-input> | ||||
|         </div> | ||||
|         <div id="panel" v-if="editRow.plottingStatus == 0"></div> | ||||
|         <div class="container" id="container"></div> | ||||
|         <el-button-group | ||||
|           style="margin-top: 8px" | ||||
|           v-if="editRow.plottingStatus == 1" | ||||
|         > | ||||
|           <el-button type="primary" size="mini" @click="beginPoltting()" | ||||
|             >开始编辑</el-button | ||||
|           > | ||||
|           <el-button size="mini" @click="finishPoltting()">结束编辑</el-button> | ||||
|         </el-button-group> | ||||
|         <el-button-group | ||||
|           style="margin-top: 8px" | ||||
|           v-if="editRow.plottingStatus == 0" | ||||
|         > | ||||
|           <el-button size="mini" @click="draw('polygon')" | ||||
|             >开始绘制多边形</el-button | ||||
|           > | ||||
|           <!-- <el-button  size="mini" @click="close()">关闭绘制</el-button> --> | ||||
|           <el-button size="mini" @click="clear()">清除绘制</el-button> | ||||
|         </el-button-group> | ||||
|       </div> | ||||
|       <div class="dialog-footer" slot="footer"> | ||||
|         <el-button size="medium" @click="showMap = false">取消</el-button> | ||||
|         <el-button type="primary" size="medium" @click="confirm()" | ||||
|           >确认</el-button | ||||
|         > | ||||
|       </div> | ||||
|     </ai-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AMapLoader from "@amap/amap-jsapi-loader"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppGridBlock", | ||||
|   label: "网格区块", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       treeObj: { | ||||
|         treeList: [], | ||||
|         defaultProps: { | ||||
|           children: "girdList", | ||||
|           label: "girdName", | ||||
|         }, | ||||
|         defaultExpandedKeys: [], | ||||
|       }, | ||||
|       filterText: "", | ||||
|       page: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|         total: 0, | ||||
|       }, | ||||
|       searchObj: { | ||||
|         createTimeStr: "", | ||||
|         girdName: "", | ||||
|       }, | ||||
|       tableData: [], | ||||
|       info: {}, | ||||
|       ids: [], | ||||
|       showMap: false, | ||||
|       map: "", | ||||
|       polyEditor: "", | ||||
|       editRow: {}, | ||||
|       searchAddress: "", | ||||
|       mouseTool: "", | ||||
|       placeSearch: "", | ||||
|       path: [], | ||||
|       overlays: [], | ||||
|       isEdit: false, | ||||
|       searchId: "", | ||||
|       fileList: [], | ||||
|     }; | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTreeList(); | ||||
|     this.getList(); | ||||
|     this.dict.load("girdLevel", "girdType", "isLastLevel", "plottingStatus"); | ||||
|   }, | ||||
|   computed: { | ||||
|     colConfigs() { | ||||
|       let _ = this; | ||||
|       return [ | ||||
|         { type: 'selection'}, | ||||
|         { | ||||
|           prop: "girdName", | ||||
|           align: "left", | ||||
|           label: "网格名称", | ||||
|         }, | ||||
|         { | ||||
|           prop: "girdCode", | ||||
|           align: "left", | ||||
|           label: "网格编码", | ||||
|         }, | ||||
|         { | ||||
|           prop: "girdType", | ||||
|           align: "left", | ||||
|           label: "网格类型", | ||||
|           render(h, { row }) { | ||||
|             return h("span", {}, _.dict.getLabel("girdType", row.girdType)); | ||||
|           }, | ||||
|         }, | ||||
|         { | ||||
|           prop: "girdLevel", | ||||
|           align: "left", | ||||
|           label: "网格层级", | ||||
|           render(h, { row }) { | ||||
|             return h("span", {}, _.dict.getLabel("girdLevel", row.girdLevel)); | ||||
|           }, | ||||
|         }, | ||||
|         { | ||||
|           prop: "plottingStatus", | ||||
|           align: "center", | ||||
|           label: "标绘状态", | ||||
|           render(h, { row }) { | ||||
|             return h( | ||||
|               "span", | ||||
|               { | ||||
|                 style: { | ||||
|                   color: _.dict.getColor("plottingStatus", row.plottingStatus), | ||||
|                 }, | ||||
|               }, | ||||
|               _.dict.getLabel("plottingStatus", row.plottingStatus) | ||||
|             ); | ||||
|           }, | ||||
|         }, | ||||
|         { | ||||
|           prop: "createTime", | ||||
|           align: "left", | ||||
|           label: "创建时间", | ||||
|           width: 200, | ||||
|           render(h, { row }) { | ||||
|             return h("span", {}, row.createTime.substring(0, 11)); | ||||
|           }, | ||||
|         }, | ||||
|         { | ||||
|           prop: "girdMemberNames", | ||||
|           align: "left", | ||||
|           label: "网格员", | ||||
|         }, | ||||
|       ]; | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     handleNodeClick(val) { | ||||
|       console.log(val); | ||||
|       this.info = { ...val }; | ||||
|       this.searchId = val.id; | ||||
|       this.getList(); | ||||
|     }, | ||||
|     getTreeList() { | ||||
|       this.instance | ||||
|         .post("/app/appgirdinfo/listByTop", null, null) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.treeObj.treeList = [...res.data]; | ||||
|             this.info = { ...this.treeObj.treeList[0] }; | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|     filterNode(value, data) { | ||||
|       if (!value) return true; | ||||
|       return data.girdName.indexOf(value) !== -1; | ||||
|     }, | ||||
|     deleteById(ids) { | ||||
|       ids && | ||||
|         this.$confirm("是否要删除该网格区块?", { | ||||
|           type: "error", | ||||
|         }) | ||||
|           .then(() => { | ||||
|             this.instance | ||||
|               .post("/app/appgirdinfo/delete", null, { | ||||
|                 params: { ids }, | ||||
|               }) | ||||
|               .then((res) => { | ||||
|                 if (res?.code == 0) { | ||||
|                   this.$message.success("删除成功!"); | ||||
|  | ||||
|                   this.getList(); | ||||
|                 } | ||||
|               }); | ||||
|           }) | ||||
|           .catch(() => {}); | ||||
|     }, | ||||
|     deleteTree(ids) { | ||||
|       ids && | ||||
|         this.$confirm("是否要删除该网格区块?", { | ||||
|           type: "error", | ||||
|         }) | ||||
|           .then(() => { | ||||
|             this.instance | ||||
|               .post("/app/appgirdinfo/delete", null, { | ||||
|                 params: { ids }, | ||||
|               }) | ||||
|               .then((res) => { | ||||
|                 if (res?.code == 0) { | ||||
|                   this.$message.success("删除成功!"); | ||||
|  | ||||
|                   this.getTreeList(); | ||||
|                 } | ||||
|               }); | ||||
|           }) | ||||
|           .catch(() => {}); | ||||
|     }, | ||||
|     getList() { | ||||
|       this.instance | ||||
|         .post("/app/appgirdinfo/list", null, { | ||||
|           params: { | ||||
|             ...this.searchObj, | ||||
|             ...this.page, | ||||
|             parentGirdId: this.searchId, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res?.data) { | ||||
|             this.tableData = res.data.records; | ||||
|             this.page.total = res.data.total; | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|     handleSelectionChange(val) { | ||||
|       this.ids = []; | ||||
|       val.map((e) => { | ||||
|         this.ids.push(e.id); | ||||
|       }); | ||||
|     }, | ||||
|     //添加二级网格 | ||||
|     addTwoLevel() { | ||||
|       this.info = { ...this.treeObj.treeList[0] }; | ||||
|       this.toAdd() | ||||
|     }, | ||||
|     toAdd() { | ||||
|       this.$emit('change', { | ||||
|         type: 'Add', | ||||
|         params: this.info, | ||||
|         isEdit: this.isEdit | ||||
|       }) | ||||
|     }, | ||||
|     goBack() { | ||||
|       this.isAdd = false; | ||||
|       this.$nextTick(() => { | ||||
|         this.getList(); | ||||
|         this.getTreeList(); | ||||
|       }); | ||||
|     }, | ||||
|     poltting(row) { | ||||
|       this.showMap = true; | ||||
|       this.editRow = { ...row }; | ||||
|       AMapLoader.load({ | ||||
|         key: "b553334ba34f7ac3cd09df9bc8b539dc", // 申请好的Web端开发者Key,首次调用 load 时必填 | ||||
|         version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 | ||||
|         plugins: ["AMap.PolygonEditor", "AMap.MouseTool", "AMap.PlaceSearch"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 | ||||
|         AMapUI: { | ||||
|           // 是否加载 AMapUI,缺省不加载 | ||||
|           version: "1.1", // AMapUI 缺省 1.1 | ||||
|           plugins: [], // 需要加载的 AMapUI ui插件 | ||||
|         }, | ||||
|       }) | ||||
|         .then((AMap) => { | ||||
|           this.map = new AMap.Map("container", { | ||||
|             resizeEnable: true, | ||||
|             zoom: 14, | ||||
|           }); | ||||
|           if (this.editRow.plottingStatus == 1) { | ||||
|             let path = []; | ||||
|             this.editRow.points.map((e, index) => { | ||||
|               path[index] = [e.lng, e.lat]; | ||||
|             }); | ||||
|             let polygon = new AMap.Polygon({ | ||||
|               path: path, | ||||
|               strokeColor: "#FF33FF", | ||||
|               strokeWeight: 6, | ||||
|               strokeOpacity: 0.2, | ||||
|               fillOpacity: 0.4, | ||||
|               fillColor: "#1791fc", | ||||
|               zIndex: 50, | ||||
|               bubble: true, | ||||
|             }); | ||||
|             this.map.add([polygon]); | ||||
|             this.map.setFitView(); | ||||
|             this.polyEditor = new AMap.PolygonEditor(this.map, polygon); | ||||
|           } else { | ||||
|             this.mouseTool = new AMap.MouseTool(this.map); | ||||
|             this.placeSearch = new AMap.PlaceSearch({ | ||||
|               pageSize: 3, // 单页显示结果条数 | ||||
|               pageIndex: 1, // 页码 | ||||
|               city: "", // 兴趣点城市 | ||||
|               citylimit: false, //是否强制限制在设置的城市内搜索 | ||||
|               map: this.map, // 展现结果的地图实例 | ||||
|               panel: "panel", // 结果列表将在此容器中进行展示。 | ||||
|               autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围 | ||||
|             }); | ||||
|             this.map.setZoomAndCenter(14, [117.147097, 36.72081], false, 600); | ||||
|             this.eventOn(); | ||||
|           } | ||||
|         }) | ||||
|         .catch((e) => { | ||||
|           console.log(e); | ||||
|         }); | ||||
|     }, | ||||
|     see(row) { | ||||
|       this.info = { ...row }; | ||||
|       this.isEdit = true; | ||||
|      this.toAdd() | ||||
|     }, | ||||
|     draw(type) { | ||||
|       switch (type) { | ||||
|         case "marker": { | ||||
|           this.mouseTool.marker({ | ||||
|             //同Marker的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|         case "polyline": { | ||||
|           this.mouseTool.polyline({ | ||||
|             strokeColor: "#80d8ff", | ||||
|             //同Polyline的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|         case "polygon": { | ||||
|           this.mouseTool.polygon({ | ||||
|             fillColor: "#00b0ff", | ||||
|             strokeColor: "#80d8ff", | ||||
|             borderWeight: 2, | ||||
|             strokeWeight: 4, | ||||
|             //同Polygon的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|         case "rectangle": { | ||||
|           this.mouseTool.rectangle({ | ||||
|             fillColor: "#00b0ff", | ||||
|             strokeColor: "#80d8ff", | ||||
|             //同Polygon的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|         case "circle": { | ||||
|           this.mouseTool.circle({ | ||||
|             fillColor: "#00b0ff", | ||||
|             strokeColor: "#80d8ff", | ||||
|             //同Circle的Option设置 | ||||
|           }); | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     //map搜索 | ||||
|     addressChange(val) { | ||||
|       this.placeSearch.search(val); | ||||
|     }, | ||||
|     close() { | ||||
|       this.mouseTool.close(true); | ||||
|     }, | ||||
|     clear() { | ||||
|       this.map.remove(this.overlays); | ||||
|       this.overlays = []; | ||||
|       this.path = []; | ||||
|     }, | ||||
|     beginPoltting() { | ||||
|       this.polyEditor.open(); | ||||
|     }, | ||||
|     finishPoltting() { | ||||
|       this.polyEditor.close(); | ||||
|     }, | ||||
|     confirm() { | ||||
|       let path = []; | ||||
|       if (this.editRow.plottingStatus == 1) { | ||||
|         this.polyEditor | ||||
|           .getTarget() | ||||
|           .getPath() | ||||
|           .map((e) => { | ||||
|             path.push({ lng: e.lng, lat: e.lat }); | ||||
|           }); | ||||
|       } else { | ||||
|         path = [...this.path]; | ||||
|       } | ||||
|       delete this.editRow.points; | ||||
|       this.instance | ||||
|         .post( | ||||
|           `/app/appgirdinfo/addOrUpdate`, | ||||
|           { | ||||
|             ...this.editRow, | ||||
|             points: path, | ||||
|           }, | ||||
|           null | ||||
|         ) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.getList(); | ||||
|             this.showMap = false; | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|     eventOn() { | ||||
|       this.path = []; | ||||
|       this.overlays = []; | ||||
|       this.map.on("mousemove", this.showInfoMove, this); | ||||
|       this.mouseTool.on("draw", ({ type, obj }) => { | ||||
|         obj.getPath().map((e) => { | ||||
|           this.path.push({ lat: e.getLat(), lng: e.getLng() }); | ||||
|         }); | ||||
|         this.overlays.push(obj); | ||||
|       }); | ||||
|     }, | ||||
|     resetSearch() { | ||||
|       Object.keys(this.searchObj).map((e) => { | ||||
|         this.searchObj[e] = ""; | ||||
|       }); | ||||
|       this.getList(); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .app-grid-block { | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|  | ||||
|   .mt10 { | ||||
|     padding: 8px 0; | ||||
|   } | ||||
|  | ||||
|   .map { | ||||
|     width: 780px; | ||||
|     position: relative; | ||||
|     overflow: hidden; | ||||
|  | ||||
|     .container { | ||||
|       width: 760px; | ||||
|       height: 420px; | ||||
|       border-radius: 2px; | ||||
|       border: 1px solid #d0d4dc; | ||||
|     } | ||||
|  | ||||
|     #panel { | ||||
|       position: absolute; | ||||
|       height: 400px; | ||||
|       right: 30px; | ||||
|       top: 20px; | ||||
|       width: 280px; | ||||
|       overflow: hidden; | ||||
|       z-index: 10000; | ||||
|     } | ||||
|  | ||||
|     .tipinput { | ||||
|       position: absolute; | ||||
|       width: 200px; | ||||
|       height: 38px; | ||||
|       left: 20px; | ||||
|       top: 20px; | ||||
|       z-index: 10000; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .treePanel { | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|  | ||||
|     .el-tree { | ||||
|       min-height: 0; | ||||
|       flex: 1; | ||||
|     } | ||||
|  | ||||
|     footer { | ||||
|       width: 100%; | ||||
|       height: 32px; | ||||
|       background-color: #fff; | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|  | ||||
|       span { | ||||
|         width: 33.33%; | ||||
|         text-align: center; | ||||
|         cursor: pointer; | ||||
|       } | ||||
|  | ||||
|       .el-button { | ||||
|         width: 33.33%; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										6
									
								
								packages/2.0.5/AppGridBlock/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								packages/2.0.5/AppGridBlock/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| import component from './AppGridBlock.vue' | ||||
|  | ||||
| component.install = function (Vue) { | ||||
|   Vue.component(component.name, component) | ||||
| } | ||||
| export default component | ||||
							
								
								
									
										70
									
								
								packages/2.0.5/AppGridMap/AppGridMap.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								packages/2.0.5/AppGridMap/AppGridMap.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| <template> | ||||
|   <div class="AppGridMap"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component | ||||
|         ref="component" | ||||
|         :is="component" | ||||
|         @change="onChange" | ||||
|         :params="params" | ||||
|         :instance="instance" | ||||
|         :dict="dict" | ||||
|       ></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from "./components/list"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppGridMap", | ||||
|   label: "网格地图", | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: "List", | ||||
|       params: {}, | ||||
|       include: [], | ||||
|     }; | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     List, | ||||
|   }, | ||||
|  | ||||
|   mounted() {}, | ||||
|  | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === "Add") { | ||||
|         this.component = "Add"; | ||||
|         this.params = data.params; | ||||
|       } | ||||
|  | ||||
|       if (data.type === "list") { | ||||
|         this.component = "List"; | ||||
|         this.params = data.params; | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getList(); | ||||
|           } | ||||
|         }); | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppGridMap { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										710
									
								
								packages/2.0.5/AppGridMap/components/list.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										710
									
								
								packages/2.0.5/AppGridMap/components/list.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,710 @@ | ||||
| <template> | ||||
|   <div class="map"> | ||||
|     <div id="mapContainer"></div> | ||||
|     <div class="drawer" ref="drawer"> | ||||
|       <div class="drawer-content"> | ||||
|         <header> | ||||
|           <h3>网格管理</h3> | ||||
|           <!-- <div class="online"> | ||||
|             <p> | ||||
|               <span>人员总数:</span> | ||||
|               <span>{{ member.allMemberNumber }}</span> | ||||
|             </p> | ||||
|             <p> | ||||
|               <span>在线人员:</span> | ||||
|               <span style="color: #19d286">{{ member.onlineNumber }}</span> | ||||
|             </p> | ||||
|           </div> | ||||
|           <div class="circle"> | ||||
|             <el-progress | ||||
|               type="circle" | ||||
|               :width="46" | ||||
|               :stroke-width="4" | ||||
|               :percentage="percentage()" | ||||
|               color="#19D286" | ||||
|             ></el-progress> | ||||
|           </div> --> | ||||
|         </header> | ||||
|         <!-- <ul class="nav"> | ||||
|           <li | ||||
|             v-for="(e, index) in navList" | ||||
|             :key="index" | ||||
|             @click="navClick(index)" | ||||
|             :class="{ active: activeIndex == index }" | ||||
|           > | ||||
|             {{ e.title }} | ||||
|           </li> | ||||
|         </ul> --> | ||||
|         <div v-show="activeIndex == 0" class="tree"> | ||||
|           <div class="map-search"> | ||||
|             <el-select | ||||
|               size="mini" | ||||
|               style="width: 80px" | ||||
|               @change="getMemberList()" | ||||
|               v-model="searchObj.onlineStatus" | ||||
|               placeholder="全部" | ||||
|               clearable | ||||
|             > | ||||
|               <el-option | ||||
|                 v-for="(item, i) in dict.getDict('onlineStatus')" | ||||
|                 :key="i" | ||||
|                 :label="item.dictName" | ||||
|                 :value="item.dictValue" | ||||
|               ></el-option> | ||||
|             </el-select> | ||||
|             <el-input | ||||
|               style="width: 164px" | ||||
|               @change="getMemberList()" | ||||
|               placeholder="请输入网格员姓名" | ||||
|               v-model="searchObj.girdMemberName" | ||||
|               size="mini" | ||||
|               @keyup.enter.native="getMemberList()" | ||||
|               suffix-icon="el-icon-search" | ||||
|             > | ||||
|             </el-input> | ||||
|           </div> | ||||
|           <header class="header"> | ||||
|             <span>人员列表</span> | ||||
|           </header> | ||||
|           <ul class="member-list" v-if="member.memberList.length > 0"> | ||||
|             <li | ||||
|               v-for="(e, index) in member.memberList" | ||||
|               :key="index" | ||||
|               @click="clickMember(e)" | ||||
|               :class="{ active: activeId == e.id }" | ||||
|             > | ||||
|               <span | ||||
|                 class="iconfont iconzxjyzdls" | ||||
|                 :style="{ | ||||
|                   color: e.onlineStatus == 1 ? '#19D286' : 'rgb(178, 178, 201)', | ||||
|                 }" | ||||
|               ></span> | ||||
|               <span>{{ e.name }}</span> | ||||
|             </li> | ||||
|           </ul> | ||||
|           <div v-if="member.memberList.length == 0" class="empty">暂无数据</div> | ||||
|         </div> | ||||
|         <div  v-show="activeIndex == 1" class="tree"> | ||||
|           <div class="input"> | ||||
|             <el-input | ||||
|               placeholder="请输入网格名称" | ||||
|               v-model="filterText" | ||||
|               size="mini" | ||||
|               suffix-icon="el-icon-search" | ||||
|             > | ||||
|             </el-input> | ||||
|           </div> | ||||
|           <header class="header"> | ||||
|             <span>网格列表</span> | ||||
|           </header> | ||||
|           <div class="tree-div"> | ||||
|             <el-tree | ||||
|               :data="treeObj.treeList" | ||||
|               :props="treeObj.defaultProps" | ||||
|               @node-click="handleNodeClick" | ||||
|               node-key="id" | ||||
|               ref="tree" | ||||
|               :filter-node-method="filterNode" | ||||
|               default-expand-all | ||||
|               highlight-current | ||||
|             > | ||||
|             </el-tree> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="drawer-btn" @click="control()" ref="drawerBtn"> | ||||
|       <span | ||||
|         class="iconfont iconArrow_Left" | ||||
|         ref="icon" | ||||
|         @click="changeIcon()" | ||||
|       ></span> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import AMapLoader from "@amap/amap-jsapi-loader"; | ||||
| import { mapState } from 'vuex' | ||||
| export default { | ||||
|   name: "AppGridMap", | ||||
|   label: "网格地图", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       map: '', | ||||
|       overlays: [], | ||||
|       drawer: false, | ||||
|       navList: [ | ||||
|         // { id: 0, title: "网格员" }, | ||||
|         { id: 1, title: "网格" }, | ||||
|       ], | ||||
|       activeIndex: 1, | ||||
|       filterText: "", | ||||
|       treeObj: { | ||||
|         treeList: [], | ||||
|         defaultProps: { | ||||
|           children: "girdList", | ||||
|           label: "girdName", | ||||
|         }, | ||||
|         defaultExpandedKeys: [], | ||||
|       }, | ||||
|       polygon: "", | ||||
|       path: [], | ||||
|       searchObj: { | ||||
|         onlineStatus: "", | ||||
|         girdMemberName: "", | ||||
|       }, | ||||
|       member: { | ||||
|         memberList: [], | ||||
|       }, | ||||
|       infoWindowHtml: "", | ||||
|       marker: {}, | ||||
|       activeId: null, | ||||
|     }; | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|   }, | ||||
|   created() { | ||||
|     this.areaId = this.user.info.areaId | ||||
|   }, | ||||
|   mounted() { | ||||
|     // this.getMemberList(); | ||||
|     this.getTreeList() | ||||
|   }, | ||||
|   watch: { | ||||
|     filterText(val) { | ||||
|       this.$refs.tree.filter(val); | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     filterNode(value, data) { | ||||
|       if (!value) return true; | ||||
|       return data.girdName.indexOf(value) !== -1; | ||||
|     }, | ||||
|     getTreeList() { | ||||
|       this.instance.post(`/app/appgirdinfo/listAll`, null, null).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.treeObj.treeList = res.data; | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     handleNodeClick(val) { | ||||
|       let path = []; | ||||
|       if (val.points) { | ||||
|         val.points.map((e, index) => { | ||||
|           path[index] = [e.lng, e.lat]; | ||||
|         }); | ||||
|       } | ||||
|       this.initMap(path); | ||||
|     }, | ||||
|     initMap(path, marker, initMakers) { | ||||
|       AMapLoader.load({ | ||||
|         key: "b553334ba34f7ac3cd09df9bc8b539dc", // 申请好的Web端开发者Key,首次调用 load 时必填 | ||||
|         version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 | ||||
|         plugins: ["AMap.ToolBar", "AMap.Scale", "AMap.InfoWindow"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 | ||||
|         AMapUI: { | ||||
|           // 是否加载 AMapUI,缺省不加载 | ||||
|           version: "1.1", // AMapUI 缺省 1.1 | ||||
|           plugins: [], // 需要加载的 AMapUI ui插件 | ||||
|         }, | ||||
|       }) | ||||
|         .then((AMap) => { | ||||
|           this.map = new AMap.Map("mapContainer", { | ||||
|             resizeEnable: true, | ||||
|             zoom: 13, | ||||
|           }); | ||||
|           this.map.setZoomAndCenter(14, [117.147097, 36.72081], false, 600); | ||||
|           if (path) { | ||||
|             this.polygon = new AMap.Polyline({ | ||||
|               path: path, | ||||
|               strokeColor: "#FF33FF", | ||||
|               strokeWeight: 6, | ||||
|               strokeStyle: "solid", | ||||
|               strokeOpacity: 1, | ||||
|               fillColor: "#1791fc", | ||||
|               zIndex: 50, | ||||
|               lineJoin: "round", | ||||
|               lineCap: "round", | ||||
|             }); | ||||
|             this.map.add(this.polygon); | ||||
|             this.map.setFitView(); | ||||
|           } | ||||
|           if (marker) { | ||||
|             console.log(marker); | ||||
|             let infoWindow = new AMap.InfoWindow({ | ||||
|               position: new AMap.LngLat(marker.lng, marker.lat), | ||||
|               offset: new AMap.Pixel(0, -30), | ||||
|               content: this.infoWindowHtml, | ||||
|             }); | ||||
|             let markerDot = new AMap.Marker({ | ||||
|               map: this.map, | ||||
|               position: new AMap.LngLat(marker.lng, marker.lat), | ||||
|             }); | ||||
|             markerDot.on("click", () => { | ||||
|               infoWindow.open(this.map); | ||||
|             }); | ||||
|             infoWindow.open(this.map); | ||||
|             this.getLngLat(marker); | ||||
|             this.map.setZoomAndCenter(13, [marker.lng, marker.lat], false, 600); | ||||
|           } | ||||
|           if (initMakers) { | ||||
|             let markerList = []; | ||||
|             initMakers.map((e) => { | ||||
|               markerList.push( | ||||
|                 new AMap.Marker({ | ||||
|                   position: new AMap.LngLat(e.lng, e.lat), | ||||
|                   label: { | ||||
|                     content: `<p class='title_info'>${e.name}</p>`, | ||||
|                     direction: "center", | ||||
|                     offset: new AMap.Pixel(0, -30), | ||||
|                   }, | ||||
|                 }) | ||||
|               ); | ||||
|             }); | ||||
|             this.map.add(markerList); | ||||
|           } | ||||
|           this.map.addControl(new AMap.Scale()); | ||||
|           this.map.addControl(new AMap.ToolBar()); | ||||
|           this.eventOn(); | ||||
|         }) | ||||
|         .catch((e) => { | ||||
|           console.log(e); | ||||
|         }); | ||||
|     }, | ||||
|     //地图事件绑定 | ||||
|     eventOn() { | ||||
|       this.map.on("mousemove", this.showInfoMove, this); | ||||
|     }, | ||||
|     showInfoMove(e) {}, | ||||
|     hasClass(ele, cls) { | ||||
|       return ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)")); | ||||
|     }, | ||||
|     addClass(ele, cls) { | ||||
|       if (!this.hasClass(ele, cls)) ele.className += " " + cls; | ||||
|     }, | ||||
|     removeClass(ele, cls) { | ||||
|       if (this.hasClass(ele, cls)) { | ||||
|         const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)"); | ||||
|         ele.className = ele.className.replace(reg, " "); | ||||
|       } | ||||
|     }, | ||||
|     changClass(ele, className) { | ||||
|       if (!this.hasClass(ele, className)) { | ||||
|         this.addClass(ele, className); | ||||
|       } else { | ||||
|         this.removeClass(ele, className); | ||||
|       } | ||||
|     }, | ||||
|     changeIcon() { | ||||
|       this.changClass(this.$refs.icon, "iconArrow_Right"); | ||||
|     }, | ||||
|     control() { | ||||
|       this.changClass(this.$refs.drawer, "hide"); | ||||
|       this.changClass(this.$refs.drawerBtn, "btn-hide"); | ||||
|     }, | ||||
|     navClick(index) { | ||||
|       this.activeIndex = index; | ||||
|       this.initMap(); | ||||
|       if (index == 1) { | ||||
|         this.filterText = ""; | ||||
|         this.getTreeList(); | ||||
|       } else { | ||||
|         this.searchObj = { | ||||
|           onlineStatus: "", | ||||
|           girdMemberName: "", | ||||
|         }; | ||||
|         this.getMemberList(); | ||||
|       } | ||||
|     }, | ||||
|     percentage() { | ||||
|       if (this.member.onlineNumber == 0) { | ||||
|         return 0; | ||||
|       } else { | ||||
|         return ( | ||||
|           100 * | ||||
|           (this.member.onlineNumber / this.member.allMemberNumber) | ||||
|         ).toFixed(2); | ||||
|       } | ||||
|     }, | ||||
|     getMemberList() { | ||||
|       this.instance | ||||
|         .post( | ||||
|           `/app/appgirdmemberinfo/queryGirdMemberByMap`, | ||||
|           { ...this.searchObj }, | ||||
|           null | ||||
|         ) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             let markers = []; | ||||
|             this.member = res.data; | ||||
|             this.member.memberList.map((e) => { | ||||
|               if (e.onlineStatus == "1") { | ||||
|                 markers.push({ lng: e.lng, lat: e.lat, name: e.name }); | ||||
|               } | ||||
|             }); | ||||
|             this.initMap(null, null, markers); | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|     clickMember(marker) { | ||||
|       if (marker.onlineStatus == 1) { | ||||
|         this.activeId = marker.id; | ||||
|         this.marker = marker; | ||||
|         this.infoWindowContent(marker); | ||||
|       } | ||||
|     }, | ||||
|     infoWindowContent(marker) { | ||||
|       this.instance | ||||
|         .post(`/app/location/xyToAddress`, null, { | ||||
|           params: { | ||||
|             x: marker.lat, | ||||
|             y: marker.lng, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.infoWindowHtml = `<div class="info"> | ||||
|                                         <p> | ||||
|                                             <span class="name">${marker.name}</span> | ||||
|                                             <span class="lat">${marker.lng},${marker.lat}</span> | ||||
|                                         </p> | ||||
|                                         <p> | ||||
|                                             <span class="lat">${res.data}</span> | ||||
|                                         </p> | ||||
|                                         <p class="address"> | ||||
|                                             <span class="iconfont iconarea" id="addressSpan">当日轨迹</span> | ||||
|                                         </p> | ||||
|                                     </div>`; | ||||
|             this.initMap(false, marker); | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|     getLngLat(marker) { | ||||
|       let span = document.getElementById("addressSpan"); | ||||
|       span.addEventListener("click", this.queryTrajectory); | ||||
|     }, | ||||
|     queryTrajectory() { | ||||
|       this.instance | ||||
|         .post(`/app/appgirdmembertrajectory/queryTrajectory`, null, { | ||||
|           params: { | ||||
|             userId: this.marker.userId, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             let path = []; | ||||
|             if (res.data) { | ||||
|               res.data.map((e, index) => { | ||||
|                 path[index] = [e.lng, e.lat]; | ||||
|               }); | ||||
|             } | ||||
|             this.initMap(path, this.marker); | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .map { | ||||
|   height: 100%; | ||||
|   width: 100%; | ||||
|   position: relative; | ||||
|   #mapContainer { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|   } | ||||
|   .drawer-btn { | ||||
|     position: absolute; | ||||
|     left: 280px; | ||||
|     bottom: 0; | ||||
|     top: 0; | ||||
|     margin: auto; | ||||
|     width: 20px; | ||||
|     height: 24px; | ||||
|     border-top: 40px solid transparent; | ||||
|     border-bottom: 40px solid transparent; | ||||
|     border-left: 16px solid #333c53; | ||||
|     border-right: 0px solid transparent; | ||||
|     transition: all 0.5s ease-in-out; | ||||
|     cursor: pointer; | ||||
|     .iconfont { | ||||
|       position: absolute; | ||||
|       font-size: 26px; | ||||
|       color: rgb(255, 255, 255); | ||||
|       left: -21px; | ||||
|       top: -14px; | ||||
|       transition: all 0.5s ease-in-out; | ||||
|     } | ||||
|   } | ||||
|   .btn-hide { | ||||
|     left: 0; | ||||
|   } | ||||
|   .drawer { | ||||
|     width: 280px; | ||||
|     height: 100%; | ||||
|     background: #333c53; | ||||
|     position: absolute; | ||||
|     z-index: 1000; | ||||
|     top: 0; | ||||
|     left: 0; | ||||
|     visibility: visible; | ||||
|     opacity: 1; | ||||
|     transition: all 0.5s ease-in-out; | ||||
|     .drawer-content { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|       padding: 0 16px; | ||||
|       box-sizing: border-box; | ||||
|       header { | ||||
|         height: 76px; | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         box-sizing: border-box; | ||||
|         h3 { | ||||
|           color: #fff; | ||||
|           font-size: 18px; | ||||
|         } | ||||
|         .online { | ||||
|           color: #fff; | ||||
|           font-size: 12px; | ||||
|           padding-left: 16px; | ||||
|         } | ||||
|         .circle { | ||||
|           width: 40px; | ||||
|           height: 40px; | ||||
|           padding-left: 16px; | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           ::v-deep .el-progress__text { | ||||
|             color: #19d286; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       .nav { | ||||
|         width: 100%; | ||||
|         height: 28px; | ||||
|         display: flex; | ||||
|         padding: 0; | ||||
|         margin: 0; | ||||
|         li { | ||||
|           width: 50%; | ||||
|           height: 28px; | ||||
|           line-height: 28px; | ||||
|           text-align: center; | ||||
|           font-size: 12px; | ||||
|           background: #1d2336; | ||||
|           border-radius: 0px 3px 3px 0px; | ||||
|           color: #8899bb; | ||||
|           cursor: pointer; | ||||
|         } | ||||
|         .active { | ||||
|           background: #3e4a69; | ||||
|           color: #fff; | ||||
|           border-radius: 3px 0px 0px 3px; | ||||
|         } | ||||
|       } | ||||
|       .tree { | ||||
|         height: calc(100% - 28px - 76px); | ||||
|         overflow: auto; | ||||
|         border-radius: 4px; | ||||
|         overflow: hidden; | ||||
|         .map-search { | ||||
|           display: flex; | ||||
|           padding: 8px 0; | ||||
|           justify-content: space-between; | ||||
|           ::v-deep  .el-input__inner { | ||||
|             color: #fff; | ||||
|           } | ||||
|         } | ||||
|         .member-list { | ||||
|           width: 100%; | ||||
|           height: calc(100% - 44px - 28px); | ||||
|           overflow: auto; | ||||
|           padding: 0; | ||||
|           margin: 0; | ||||
|           li { | ||||
|             width: 100%; | ||||
|             height: 32px; | ||||
|             display: flex; | ||||
|             padding: 0 8px; | ||||
|             align-items: center; | ||||
|             color: #fff; | ||||
|             margin: 0; | ||||
|             cursor: pointer; | ||||
|             span { | ||||
|               padding-right: 8px; | ||||
|             } | ||||
|           } | ||||
|           .active { | ||||
|             background: #1d2336; | ||||
|           } | ||||
|           &::-webkit-scrollbar { | ||||
|             /*滚动条整体样式*/ | ||||
|             width: 10px; /*高宽分别对应横竖滚动条的尺寸*/ | ||||
|             height: 1px; | ||||
|           } | ||||
|           &::-webkit-scrollbar-thumb { | ||||
|             /*滚动条里面小方块*/ | ||||
|             border-radius: 10px; | ||||
|             box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); | ||||
|             background: #1a1e2c; | ||||
|           } | ||||
|           &::-webkit-scrollbar-track { | ||||
|             /*滚动条里面轨道*/ | ||||
|             box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); | ||||
|             border-radius: 10px; | ||||
|             background: #ededed; | ||||
|             background: #282f45; | ||||
|           } | ||||
|         } | ||||
|         .empty { | ||||
|           padding: 20px 0; | ||||
|           color: #7a88bb; | ||||
|           text-align: center; | ||||
|         } | ||||
|         .header { | ||||
|           width: 100%; | ||||
|           height: 28px; | ||||
|           padding: 0 16px; | ||||
|           box-sizing: border-box; | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           color: #fff; | ||||
|           justify-content: space-between; | ||||
|           font-size: 14px; | ||||
|           background: #3e4a69; | ||||
|         } | ||||
|  | ||||
|         .input { | ||||
|           width: 100%; | ||||
|           padding: 8px 0; | ||||
|           ::v-deep  .el-input__inner { | ||||
|             color: #fff; | ||||
|           } | ||||
|         } | ||||
|         ::v-deep  .el-input__inner { | ||||
|           background-color: #282f45; | ||||
|           border: 1px solid #282f45; | ||||
|         } | ||||
|         .tree-div { | ||||
|           width: 100%; | ||||
|           height: calc(100% - 44px - 28px); | ||||
|           overflow: auto; | ||||
|           &::-webkit-scrollbar { | ||||
|             /*滚动条整体样式*/ | ||||
|             width: 10px; /*高宽分别对应横竖滚动条的尺寸*/ | ||||
|             height: 1px; | ||||
|           } | ||||
|           &::-webkit-scrollbar-thumb { | ||||
|             /*滚动条里面小方块*/ | ||||
|             border-radius: 10px; | ||||
|             box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); | ||||
|             background: #1a1e2c; | ||||
|           } | ||||
|           &::-webkit-scrollbar-track { | ||||
|             /*滚动条里面轨道*/ | ||||
|             box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); | ||||
|             border-radius: 10px; | ||||
|             background: #ededed; | ||||
|             background: #282f45; | ||||
|           } | ||||
|         } | ||||
|         footer { | ||||
|           width: 100%; | ||||
|           height: 32px; | ||||
|           background-color: #fff; | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           span { | ||||
|             width: 33.33%; | ||||
|             text-align: center; | ||||
|             cursor: pointer; | ||||
|           } | ||||
|         } | ||||
|         ::v-deep  .el-tree { | ||||
|           width: 100%; | ||||
|  | ||||
|           .el-tree__empty-block { | ||||
|             background: #333c53; | ||||
|           } | ||||
|           .el-tree-node__label { | ||||
|             color: #fff; | ||||
|           } | ||||
|           .el-tree-node__content { | ||||
|             background: #333c53; | ||||
|           } | ||||
|           .is-current > .el-tree-node__content { | ||||
|             .el-tree-node__label { | ||||
|               color: #5088ff; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   .hide { | ||||
|     left: -280px; | ||||
|     opacity: 0; | ||||
|     visibility: hidden; | ||||
|   } | ||||
|   .btn { | ||||
|     position: absolute; | ||||
|     top: 100px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| <style lang="scss"> | ||||
| .map { | ||||
|   .info { | ||||
|     width: 280px; | ||||
|     height: 98px; | ||||
|     background: #fff; | ||||
|     padding: 8px 0 0 12px; | ||||
|     box-sizing: border-box; | ||||
|     p { | ||||
|       margin: 0; | ||||
|       padding: 0; | ||||
|     } | ||||
|     p { | ||||
|       line-height: 20px; | ||||
|       .name { | ||||
|         color: #333; | ||||
|         font-size: 16px; | ||||
|         font-weight: bold; | ||||
|       } | ||||
|       .lat { | ||||
|         font-size: 12px; | ||||
|         color: #999; | ||||
|       } | ||||
|     } | ||||
|     .address { | ||||
|       color: #999; | ||||
|       line-height: 40px; | ||||
|       font-size: 12px; | ||||
|       cursor: pointer; | ||||
|     } | ||||
|   } | ||||
|   .title_info { | ||||
|     width: 68px; | ||||
|     font-size: 14px; | ||||
|     font-weight: bold; | ||||
|     height: 20px; | ||||
|     text-align: center; | ||||
|     line-height: 20px; | ||||
|     border-radius: 4px; | ||||
|     padding: 0; | ||||
|     margin: 0; | ||||
|   } | ||||
|   .amap-marker-label { | ||||
|     border: 1px solid rgb(141, 139, 139); | ||||
|     background-color: #fff; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										72
									
								
								packages/2.0.5/AppGridMember/AppGridMember.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								packages/2.0.5/AppGridMember/AppGridMember.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| <template> | ||||
|   <div class="AppGridMember"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component | ||||
|         ref="component" | ||||
|         :is="component" | ||||
|         @change="onChange" | ||||
|         :params="params" | ||||
|         :instance="instance" | ||||
|         :dict="dict" | ||||
|       ></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from "./components/list"; | ||||
| import Add from "./components/add"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppGridMember", | ||||
|   label: "网格管理员", | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: "List", | ||||
|       params: {}, | ||||
|       include: [], | ||||
|     }; | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     Add, | ||||
|     List, | ||||
|   }, | ||||
|  | ||||
|   mounted() {}, | ||||
|  | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === "Add") { | ||||
|         this.component = "Add"; | ||||
|         this.params = data.params; | ||||
|       } | ||||
|  | ||||
|       if (data.type === "list") { | ||||
|         this.component = "List"; | ||||
|         this.params = data.params; | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getList(); | ||||
|           } | ||||
|         }); | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppGridMember { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										451
									
								
								packages/2.0.5/AppGridMember/components/add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										451
									
								
								packages/2.0.5/AppGridMember/components/add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,451 @@ | ||||
| <template> | ||||
|   <section style="height: 100%"> | ||||
|     <ai-detail class="add"> | ||||
|       <template #title> | ||||
|         <ai-title :title="title" :isShowBack="true" :isShowBottomBorder="true" @onBackClick="cancel(false)"></ai-title> | ||||
|       </template> | ||||
|       <template #content> | ||||
|         <el-form | ||||
|           ref="rules" | ||||
|           :model="forms" | ||||
|           :rules="formRules" | ||||
|           size="small" | ||||
|           label-suffix=":" | ||||
|           label-width="136px" | ||||
|         >    | ||||
|  | ||||
|           <ai-card title="基础信息" > | ||||
|             <template #right  v-if="title=='网格员详情'"> | ||||
|               <span style="color:#2266FF;cursor: pointer;font-size: 12px;" class="iconfont iconEdit" v-if="editOne==false" @click="editOne=true">修改</span> | ||||
|               <span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editOne==true" @click="searchDetail(),editOne=false">取消</span> | ||||
|               <span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editOne==true" @click="save()">保存</span> | ||||
|             </template> | ||||
|             <template slot="content"> | ||||
|               <div class="above" v-if="editOne==true"> | ||||
|                 <div class="left"> | ||||
|                   <el-form-item label="网格员姓名" prop="name" > | ||||
|                     <el-row type="flex" justify="space-between"> | ||||
|                       <el-col :span="17"> | ||||
|                         <el-input v-model="forms.name" placeholder="请输入…" disabled></el-input> | ||||
|                       </el-col> | ||||
|                       <el-col :span="6"> | ||||
|                         <ai-person-select :instance="instance" headerTitle="帐号列表" customRightText @selectPerson="getSelectPerson" url="/admin/user/pageForWeb"  > | ||||
|                           <template v-slot:option ="{ item }"> | ||||
|                             <span class="iconfont iconProlife">{{ item.name }}</span> | ||||
|                             <span>{{ item.phone }}</span> | ||||
|                           </template> | ||||
|                         </ai-person-select> | ||||
|                       </el-col> | ||||
|                     </el-row>              | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="选用日期" prop="selectionDate" > | ||||
|                     <el-date-picker | ||||
|                       v-model="forms.selectionDate" | ||||
|                       type="date" | ||||
|                       value-format="yyyy-MM-dd" | ||||
|                       size="medium" | ||||
|                       placeholder="选择日期"> | ||||
|                     </el-date-picker> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="身份证号" prop="idNumber" > | ||||
|                       <el-input v-model="forms.idNumber" placeholder="请输入…" maxlength="18" show-word-limit></el-input> | ||||
|                   </el-form-item> | ||||
|                 </div> | ||||
|                 <div class="right"> | ||||
|                   <el-form-item label="照片" prop="photo"> | ||||
|                     <!-- <ai-uploader :instance="instance" v-model="photoList" :limit="1" @change="photoChange"></ai-uploader> --> | ||||
|                     <ai-avatar :instance="instance"  v-model="forms.photo"/> | ||||
|                   </el-form-item> | ||||
|                 </div>              | ||||
|               </div> | ||||
|               <div class="above" v-if="editOne==true"> | ||||
|                 <div class="left"> | ||||
|                   <el-form-item label="出生日期" prop="birthday" > | ||||
|                     <el-date-picker | ||||
|                         v-model="forms.birthday" | ||||
|                         type="date" | ||||
|                         value-format="yyyy-MM-dd" | ||||
|                         size="medium" | ||||
|                         placeholder="选择日期"> | ||||
|                     </el-date-picker> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="联系电话" prop="phone" > | ||||
|                     <el-input v-model.number="forms.phone" placeholder="请输入…" maxlength="11" show-word-limit></el-input> | ||||
|                   </el-form-item> | ||||
|                 </div> | ||||
|                 <div class="right"> | ||||
|                   <el-form-item label="性别" prop="sex" > | ||||
|                     <el-select size="medium" v-model="forms.sex" placeholder="请选择..." clearable> | ||||
|                       <el-option | ||||
|                         v-for="(item,i) in dict.getDict('sex')" | ||||
|                         :key="i" | ||||
|                         :label="item.dictName" | ||||
|                         :value="item.dictValue" | ||||
|                       > | ||||
|                       </el-option> | ||||
|                     </el-select> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="电子邮箱" prop="mail" > | ||||
|                       <el-input v-model="forms.mail" placeholder="请输入…"></el-input> | ||||
|                   </el-form-item> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <template  v-if="editOne==false"> | ||||
|                 <div class="above"> | ||||
|                   <div class="left"> | ||||
|                     <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                       <ai-info-item label="网格员姓名:"><span >{{forms.name}}</span></ai-info-item> | ||||
|                       <ai-info-item label="选用日期:"><span >{{forms.selectionDate}}</span></ai-info-item> | ||||
|                       <ai-info-item label="身份证号:"><span >{{forms.idNumber}}</span></ai-info-item> | ||||
|                       <ai-info-item label="性别:"><span >{{dict.getLabel('sex', forms.sex)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="出生日期:"><span >{{forms.birthday}}</span></ai-info-item> | ||||
|                       <ai-info-item label="电子邮箱:"><span >{{forms.mail}}</span></ai-info-item> | ||||
|                     </ai-wrapper> | ||||
|                   </div> | ||||
|                   <div class="right"> | ||||
|                     <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                       <ai-info-item label="照片:" v-if="forms.photo"> | ||||
|                         <span > | ||||
|                           <ai-uploader :instance="instance" v-model="photoList" disabled :limit="1" @change="photoChange"></ai-uploader> | ||||
|                         </span> | ||||
|                       </ai-info-item> | ||||
|                       <ai-info-item label="联系电话:"><span >{{forms.phone}}</span></ai-info-item> | ||||
|                     </ai-wrapper> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </template> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card title="关联信息" > | ||||
|             <template #right  v-if="title=='网格员详情'"> | ||||
|               <span style="color:#2266FF;cursor: pointer;font-size: 12px;" class="iconfont iconEdit" v-if="editTwo==false" @click="editTwo=true">修改</span> | ||||
|               <span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editTwo==true" @click="searchDetail(),editTwo=false">取消</span> | ||||
|               <span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editTwo==true" @click="save()">保存</span> | ||||
|             </template> | ||||
|             <template slot="content"> | ||||
|               <template v-if="editTwo==true"> | ||||
|                 <el-form-item label="责任网格" prop="girdInfoList" style="margin-top: 8px;">                                                                      | ||||
|                   <el-tag | ||||
|                     :key="index" | ||||
|                     v-for="(tag,index) in forms.girdInfoList" | ||||
|                     closable | ||||
|                     :disable-transitions="false" | ||||
|                     @close="handleClose(tag)"> | ||||
|                     {{tag.girdName}} | ||||
|                   </el-tag>                                       | ||||
|                   <el-button size="small" @click="showGrid=true">选择网格</el-button>                                                                           | ||||
|                 </el-form-item> | ||||
|                 <div class="above"> | ||||
|                   <div class="left"> | ||||
|                     <el-form-item label="是否特殊网格员" prop="isGirdMember" > | ||||
|                       <el-radio-group v-model="forms.isGirdMember"> | ||||
|                         <el-radio label="0">否</el-radio> | ||||
|                         <el-radio label="1">是</el-radio> | ||||
|                       </el-radio-group> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="政治面貌" prop="politicsStatus" >                                        | ||||
|                       <el-select v-model="forms.politicsStatus" size="medium" placeholder="请选择..." clearable> | ||||
|                         <el-option v-for="(item,i) in dict.getDict('politicsStatus')" :key="i" :label="item.dictName" :value="item.dictValue"></el-option> | ||||
|                       </el-select> | ||||
|                     </el-form-item> | ||||
|                   </div> | ||||
|                   <div class="right"> | ||||
|                     <el-form-item label="特殊网格员" prop="girdMemberType" v-if="forms.isGirdMember==1">                                        | ||||
|                       <el-select v-model="forms.girdMemberType" size="medium" placeholder="请选择..." clearable> | ||||
|                         <el-option v-for="(item,i) in dict.getDict('girdMemberType')" :key="i" :label="item.dictName" :value="item.dictValue"></el-option> | ||||
|                       </el-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="学历" prop="education" >                                        | ||||
|                       <el-select v-model="forms.education" size="medium" placeholder="请选择..." clearable> | ||||
|                         <el-option v-for="(item,i) in dict.getDict('education')" :key="i" :label="item.dictName" :value="item.dictValue"></el-option> | ||||
|                       </el-select> | ||||
|                     </el-form-item> | ||||
|                   </div> | ||||
|                 </div> | ||||
|                 <el-form-item label="个人简介" prop="introduction" >                                        | ||||
|                   <el-input | ||||
|                     type="textarea" | ||||
|                     maxlength="200" | ||||
|                     show-word-limit | ||||
|                     :rows="4" | ||||
|                     placeholder="请输入内容" | ||||
|                     v-model="forms.introduction"> | ||||
|                   </el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="人生格言" prop="motto" >                                        | ||||
|                   <el-input | ||||
|                     type="textarea" | ||||
|                     maxlength="200" | ||||
|                     show-word-limit | ||||
|                     :rows="4" | ||||
|                     placeholder="请输入内容" | ||||
|                     v-model="forms.motto"> | ||||
|                   </el-input> | ||||
|                 </el-form-item> | ||||
|               </template> | ||||
|               <template v-if="editTwo==false"> | ||||
|                 <ai-wrapper label-width="120px" :columnsNumber="2" style="margin-top: 16px;"> | ||||
|                   <ai-info-item label="责任网格:" style="width: 100%;"><span >{{forms.girdInfoListStr}}</span></ai-info-item> | ||||
|                   <ai-info-item label="是否特殊网格员:"><span >{{forms.isGirdMember==1?'是':'否'}}</span></ai-info-item> | ||||
|                   <ai-info-item label="特殊网格员:" v-if="forms.isGirdMember==1"><span >{{dict.getLabel('girdMemberType', forms.girdMemberType)}}</span></ai-info-item> | ||||
|                   <ai-info-item label="政治面貌:"><span >{{dict.getLabel('politicsStatus', forms.politicsStatus)}}</span></ai-info-item> | ||||
|                   <ai-info-item label="学历:"><span >{{dict.getLabel('education', forms.education)}}</span></ai-info-item> | ||||
|                   <ai-info-item label="人生格言:" style="width: 100%;"><span >{{forms.motto}}</span></ai-info-item> | ||||
|                   <ai-info-item label="个人简介:" style="width: 100%;"><span >{{forms.introduction}}</span></ai-info-item> | ||||
|                 </ai-wrapper> | ||||
|               </template> | ||||
|             </template>   | ||||
|           </ai-card> | ||||
|         </el-form> | ||||
|         <ai-dialog title="选择网格" :visible.sync="showGrid" :customFooter="true"  :destroyOnClose="true"  @opened="beforeSelectTree"  border  width="720px"> | ||||
|           <div class="grid"> | ||||
|             <el-tree :data="treeObj.treeList"  :props="treeObj.defaultProps" node-key="id"  ref="tree" :check-strictly="true"  show-checkbox | ||||
|               :default-checked-keys="treeObj.checkedKeys" default-expand-all  highlight-current>                   | ||||
|             </el-tree>  | ||||
|           </div> | ||||
|           <div class="dialog-footer" slot="footer" > | ||||
|             <el-button  size="medium" @click="showGrid=false">取消</el-button> | ||||
|             <el-button  type="primary" size="medium" @click="getCheckedTree()">确认</el-button> | ||||
|           </div> | ||||
|         </ai-dialog> | ||||
|       </template> | ||||
|       <template #footer v-if="title=='添加网格员'"> | ||||
|         <el-button @click="cancel(false)" class="delete-btn footer-btn" >取 消</el-button> | ||||
|         <el-button type="primary" @click="save()"  class="footer-btn">提 交</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "add", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|     params: Object, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       forms: { | ||||
|         birthday: "", | ||||
|         education: "", | ||||
|         girdId: "", | ||||
|         girdInfoList: [], | ||||
|         girdMemberType: "", | ||||
|         id: "", | ||||
|         introduction: "", | ||||
|         isGirdMember: "", | ||||
|         mail: "", | ||||
|         motto: "", | ||||
|         name: "", | ||||
|         phone: "", | ||||
|         photo: "", | ||||
|         politicsStatus: "", | ||||
|         selectionDate: "", | ||||
|         sex: "", | ||||
|         userId: "", | ||||
|       }, | ||||
|       showGrid: false, | ||||
|       treeObj: { | ||||
|         treeList: [], | ||||
|         defaultProps: { | ||||
|           children: "girdList", | ||||
|           label: "girdName", | ||||
|         }, | ||||
|         checkedKeys: [], | ||||
|       }, | ||||
|       photoList: [], | ||||
|       title: "添加网格员", | ||||
|       editOne: false, | ||||
|       editTwo: false, | ||||
|     }; | ||||
|   }, | ||||
|   created() { | ||||
|     if (this.params.id) { | ||||
|       this.searchDetail(); | ||||
|       this.title = "网格员详情"; | ||||
|       this.editOne = false; | ||||
|       this.editTwo = false; | ||||
|     } else { | ||||
|       this.title = "添加网格员"; | ||||
|       this.editOne = true; | ||||
|       this.editTwo = true; | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     formRules() { | ||||
|       var IdNumberPass = (rule, value, callback) => { | ||||
|         if (value) { | ||||
|           if (this.idCardNoUtil.checkIdCardNo(value)) { | ||||
|             callback(); | ||||
|           } else { | ||||
|             callback(new Error("身份证号格式错误")); | ||||
|           } | ||||
|         } else { | ||||
|           callback(new Error("请输入身份证号")); | ||||
|         } | ||||
|       }; | ||||
|       let phonePass = (rule, value, callback) => { | ||||
|         let reg = /^(?:(?:\+|00)86)?1\d{10}$/; | ||||
|         if (value) { | ||||
|           if (reg.test(value)) { | ||||
|             callback(); | ||||
|           } else { | ||||
|             callback(new Error("联系电话格式错误")); | ||||
|           } | ||||
|         } else { | ||||
|           callback(new Error("请输入联系电话")); | ||||
|         } | ||||
|       }; | ||||
|       return { | ||||
|         name: [ | ||||
|           { required: true, message: "请填写网格员姓名", trigger: "change" }, | ||||
|         ], | ||||
|         selectionDate: [ | ||||
|           { required: true, message: "请选择选用日期", trigger: "change" }, | ||||
|         ], | ||||
|         phone: [{ required: true, validator: phonePass, trigger: "blur" }], | ||||
|         idNumber: [ | ||||
|           { required: true, validator: IdNumberPass, trigger: "blur" }, | ||||
|         ], | ||||
|         girdInfoList: [ | ||||
|           { required: true, message: "请选择责任网络", trigger: "change" }, | ||||
|         ], | ||||
|         mail: [ | ||||
|           { | ||||
|             type: "email", | ||||
|             message: "请输入正确的邮箱地址", | ||||
|             trigger: ["blur", "change"], | ||||
|           }, | ||||
|         ], | ||||
|         isGirdMember: [ | ||||
|           { | ||||
|             required: true, | ||||
|             message: "请选择是否特殊网格员", | ||||
|             trigger: "change", | ||||
|           }, | ||||
|         ], | ||||
|       }; | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     cancel (isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: isRefresh ? true : false, | ||||
|       }) | ||||
|     }, | ||||
|     photoChange(val) { | ||||
|       console.log(val); | ||||
|       this.forms.photo = val[0].url; | ||||
|     }, | ||||
|     getSelectPerson(val) { | ||||
|       console.log(val); | ||||
|       this.forms.name = val.name; | ||||
|       this.forms.phone = val.phone; | ||||
|       this.forms.userId = val.id | ||||
|     }, | ||||
|     getCheckedTree() { | ||||
|       this.forms.girdInfoList = this.$refs.tree.getCheckedNodes(); | ||||
|       this.showGrid = false; | ||||
|     }, | ||||
|     handleClose(tag) { | ||||
|       this.forms.girdInfoList.splice(this.forms.girdInfoList.indexOf(tag), 1); | ||||
|     }, | ||||
|     beforeSelectTree() { | ||||
|       this.treeObj.checkedKeys = []; | ||||
|       this.instance.post(`/app/appgirdinfo/listAll`, null, null).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.treeObj.treeList = res.data; | ||||
|           this.forms.girdInfoList.map((e) => { | ||||
|             this.treeObj.checkedKeys.push(e.id); | ||||
|           }); | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     save() { | ||||
|       this.$refs["rules"].validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.instance | ||||
|             .post( | ||||
|               `/app/appgirdmemberinfo/addOrUpdate`, | ||||
|               { | ||||
|                 ...this.forms, | ||||
|               }, | ||||
|               null | ||||
|             ) | ||||
|             .then((res) => { | ||||
|               if (res.code == 0) { | ||||
|                 if (this.title == "添加网格员") { | ||||
|                   this.cancel(true) | ||||
|                 } else { | ||||
|                   this.editOne = false; | ||||
|                   this.editTwo = false; | ||||
|                   this.searchDetail(); | ||||
|                 } | ||||
|               } | ||||
|             }); | ||||
|         } else { | ||||
|           console.log("error submit!!"); | ||||
|           return false; | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     searchDetail() { | ||||
|       this.instance | ||||
|         .post(`/app/appgirdmemberinfo/queryDetailById`, null, { | ||||
|           params: { id: this.params.id }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.forms = { ...res.data }; | ||||
|             this.photoList = [{ url: this.forms.photo }]; | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .add { | ||||
|   height: 100%; | ||||
|   .ai-detail__title { | ||||
|     background-color: #fff; | ||||
|   } | ||||
|   .ai-detail__content { | ||||
|     .ai-detail__content--wrapper { | ||||
|       .el-form { | ||||
|         // background-color: #fff; | ||||
|         // padding: 0 60px; | ||||
|         .flex { | ||||
|           display: flex; | ||||
|           flex-wrap: wrap; | ||||
|           justify-content: space-between; | ||||
|           .el-form-item { | ||||
|             width: 48%; | ||||
|           } | ||||
|           .buildingTypes { | ||||
|             width: 100%; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   ::v-deep .el-tag { | ||||
|     margin-right: 8px; | ||||
|     color: #333333; | ||||
|   } | ||||
|   .footer-btn { | ||||
|     width: 92px; | ||||
|   } | ||||
|   .above{ | ||||
|     display: flex; | ||||
|     .left, .right{ | ||||
|       flex: 1; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										220
									
								
								packages/2.0.5/AppGridMember/components/list.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								packages/2.0.5/AppGridMember/components/list.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,220 @@ | ||||
| <template> | ||||
|   <ai-list class="list"> | ||||
|     <template slot="title"> | ||||
|       <ai-title title="网格员管理" :isShowBottomBorder="true"></ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar> | ||||
|         <template slot="left"> | ||||
|           <el-date-picker | ||||
|             v-model="searchObj.selectionDate" | ||||
|             type="date" | ||||
|             @change="(page.current = 1), getList()" | ||||
|             value-format="yyyy-MM-dd" | ||||
|             size="small" | ||||
|             placeholder="选用时间" | ||||
|           > | ||||
|           </el-date-picker> | ||||
|         </template> | ||||
|         <template slot="right"> | ||||
|           <el-input | ||||
|             v-model="searchObj.name" | ||||
|             size="small" | ||||
|             placeholder="网格员/网格名称" | ||||
|             @keyup.enter.native="(page.current = 1), getList()" | ||||
|             clearable | ||||
|             prefix-icon="iconfont iconSearch" | ||||
|           /> | ||||
|           <el-button | ||||
|             type="primary" | ||||
|             icon="iconfont iconSearch" | ||||
|             size="small" | ||||
|             @click="(page.current = 1), getList()" | ||||
|             >查询</el-button | ||||
|           > | ||||
|           <el-button | ||||
|             icon="el-icon-refresh-right" | ||||
|             size="small" | ||||
|             @click="resetSearch" | ||||
|             >重置</el-button | ||||
|           > | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-search-bar style="padding: 16px 0"> | ||||
|         <template slot="left"> | ||||
|           <el-button | ||||
|             icon="iconfont iconAdd" | ||||
|             type="primary" | ||||
|             size="small" | ||||
|             @click="add('')" | ||||
|             >添加</el-button | ||||
|           > | ||||
|           <el-button | ||||
|             icon="iconfont iconDelete" | ||||
|             @click="deleteById(ids.join(','))" | ||||
|             :disabled="!Boolean(ids.length)" | ||||
|             >删除</el-button | ||||
|           > | ||||
|           <!-- <ai-download :instance="instance" url="/app/appgirdinfo/downloadGirdInfo" :params="{...searchObj,ids}" fileName="网格区块"> | ||||
|                           <el-button  icon="iconfont iconExported" size="small">导出全部</el-button> | ||||
|                       </ai-download>                         | ||||
|                       <ai-import | ||||
|                           ref="import" | ||||
|                           style="margin-top: -8px;" | ||||
|                           title="导入" | ||||
|                           name="网格区块" | ||||
|                           url="/app/appgirdinfo/downloadGirdInfo" | ||||
|                           importUrl="/app/appgirdinfo/importGirdInfo" | ||||
|                           suffixName="xlsx" | ||||
|                           :customCliker="true" | ||||
|                           :instance="instance"> | ||||
|                           <template slot="tips"> | ||||
|                               <p>如果表格中已经存在数据,则会被本次导入的数据覆盖;不存在数据,系统将生成新的标准记录;</p> | ||||
|                           </template> | ||||
|                           <el-button  size="small" icon="iconfont iconImport">导入</el-button> | ||||
|                       </ai-import> --> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table | ||||
|         :tableData="tableData" | ||||
|         :col-configs="colConfigs" | ||||
|         :total="page.total" | ||||
|         ref="aitableex" | ||||
|         :current.sync="page.current" | ||||
|         :size.sync="page.size" | ||||
|         @selection-change="(v) => (ids = v.map((e) => e.id))" | ||||
|         @getList="getList()" | ||||
|       > | ||||
|         <el-table-column label="操作" slot="options" align="center"> | ||||
|           <template v-slot="{ row }"> | ||||
|             <el-button type="text" @click="add(row.id)">查看</el-button> | ||||
|             <el-button type="text" @click="deleteById(row.id)">删除</el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "list", | ||||
|   label: "网格员管理", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       searchObj: { | ||||
|         name: "", | ||||
|         selectionDate: "", | ||||
|       }, | ||||
|       page: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|         total: 0, | ||||
|       }, | ||||
|       goAdd: false, | ||||
|       tableData: [], | ||||
|       fileList: [], | ||||
|       ids: [], | ||||
|       detail: {}, | ||||
|     }; | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load("sex", "girdMemberType", "politicsStatus", "education"); | ||||
|     this.getList(); | ||||
|   }, | ||||
|   computed: { | ||||
|     colConfigs() { | ||||
|       let _ = this; | ||||
|       return [ | ||||
|         { | ||||
|           type: "selection", | ||||
|         }, | ||||
|         { | ||||
|           prop: "name", | ||||
|           align: "center", | ||||
|           label: "网格员姓名", | ||||
|         }, | ||||
|         { | ||||
|           prop: "girdInfoListStr", | ||||
|           align: "left", | ||||
|           label: "责任网格", | ||||
|         }, | ||||
|         { | ||||
|           prop: "phone", | ||||
|           align: "left", | ||||
|           label: "联系电话", | ||||
|         }, | ||||
|         { | ||||
|           prop: "selectionDate", | ||||
|           align: "center", | ||||
|           label: "选用时间", | ||||
|         }, | ||||
|       ]; | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     getList() { | ||||
|       this.instance | ||||
|         .post("/app/appgirdmemberinfo/list", null, { | ||||
|           params: { | ||||
|             ...this.searchObj, | ||||
|             ...this.page, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records; | ||||
|             this.page.total = res.data.total; | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|     deleteById(ids) { | ||||
|       ids && | ||||
|         this.$confirm("是否要删除该网格员?", { | ||||
|           type: "error", | ||||
|         }) | ||||
|           .then(() => { | ||||
|             this.instance | ||||
|               .post("/app/appgirdmemberinfo/delete", null, { | ||||
|                 params: { ids }, | ||||
|               }) | ||||
|               .then((res) => { | ||||
|                 if (res?.code == 0) { | ||||
|                   this.$message.success("删除成功!"); | ||||
|                   this.getList(); | ||||
|                 } | ||||
|               }); | ||||
|           }) | ||||
|           .catch(() => {}); | ||||
|     }, | ||||
|     add(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'Add', | ||||
|         params: { | ||||
|           id: id || '' | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleSelectionChange(val) { | ||||
|       this.ids = []; | ||||
|       val.map((e) => { | ||||
|         this.ids.push(e.id); | ||||
|       }); | ||||
|     }, | ||||
|     resetSearch() { | ||||
|       Object.keys(this.searchObj).map((e) => { | ||||
|         this.searchObj[e] = ""; | ||||
|       }); | ||||
|       this.getList(); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| </style> | ||||
							
								
								
									
										61
									
								
								packages/2.0.5/AppHomesteadManagement/AppHomesteadManagement.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								packages/2.0.5/AppHomesteadManagement/AppHomesteadManagement.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| <template> | ||||
|   <div class="AppHomesteadManagement"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from './components/List' | ||||
| import Add from './components/Add' | ||||
|  | ||||
| export default { | ||||
|   label: '宅基地管理', | ||||
|   name: 'AppHomesteadManagement', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: 'List', | ||||
|       params: {}, | ||||
|       include: [], | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     Add, | ||||
|     List, | ||||
|   }, | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === 'add') { | ||||
|         this.component = 'Add' | ||||
|         this.params = data.params | ||||
|       } | ||||
|  | ||||
|       if (data.type == 'list') { | ||||
|         this.component = 'List' | ||||
|         this.params = data.params | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getList() | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppHomesteadManagement { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										466
									
								
								packages/2.0.5/AppHomesteadManagement/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								packages/2.0.5/AppHomesteadManagement/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,466 @@ | ||||
| <template> | ||||
|   <section style="height: 100%"> | ||||
|     <ai-detail class="Add"> | ||||
|       <!-- 返回按钮 --> | ||||
|       <template #title> | ||||
|         <ai-title :title="isEdit ? '编辑宅基地信息' : '添加宅基地'" isShowBack isShowBottomBorder @onBackClick="cancel(false)"></ai-title> | ||||
|       </template> | ||||
|       <template #content> | ||||
|         <el-form :model="formData" :rules="formRules" ref="ruleForm" label-width="150px" label-suffix=":" align-items="center"> | ||||
|           <ai-card title="户主信息" > | ||||
|             <template slot="content"> | ||||
|               <div class="flex"> | ||||
|                 <el-form-item label="姓名" prop="name"> | ||||
|                   <el-input size="small" class="user-selecter" v-model="formData.name" placeholder="请输入" clearable> | ||||
|                     <template slot="append"> | ||||
|                       <ai-person-select :instance="instance" @selectPerson="checkName"> | ||||
|                       </ai-person-select> | ||||
|                     </template> | ||||
|                   </el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="身份证号码" prop="idNumber"> | ||||
|                   <ai-id size="small" v-model="formData.idNumber" @change="IdCard(formData.idNumber)"/> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="性别" prop="sex"> | ||||
|                   <ai-select v-model="formData.sex" placeholder="请选择" :selectList="dict.getDict('sex')" disabled /> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="年龄" prop="age"> | ||||
|                   <el-input size="small" v-model="formData.age" placeholder="请输入" clearable disabled></el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="联系电话"> | ||||
|                   <el-input size="small" v-model="formData.phone" placeholder="请输入" clearable :maxlength="20"></el-input> | ||||
|                 </el-form-item> | ||||
|               </div> | ||||
|               <el-form-item label="所属村" prop="areaId"> | ||||
|                 <ai-area-get :instance="instance" v-model="formData.areaId" :name.sync="formData.areaName" /> | ||||
|               </el-form-item> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card title="宅基地情况" > | ||||
|             <template slot="content"> | ||||
|               <div class="flex"> | ||||
|                 <el-form-item label="宅基地面积"> | ||||
|                   <el-input size="small" v-model="formData.homesteadArea" placeholder="请输入" clearable maxlength="10"> | ||||
|                     <template slot="append">m²</template> | ||||
|                   </el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="房基占地面积"> | ||||
|                   <el-input size="small" v-model="formData.houseArea" placeholder="请输入" clearable maxlength="10"> | ||||
|                     <template slot="append">m²</template> | ||||
|                   </el-input> | ||||
|                 </el-form-item> | ||||
|               </div> | ||||
|               <el-form-item label="宅基地地址"> | ||||
|                 <el-input size="small" v-model="formData.homesteadAddress" placeholder="请输入" clearable maxlength="20"></el-input> | ||||
|               </el-form-item> | ||||
|               <div class="flex"> | ||||
|                 <el-form-item label="四至-东至"> | ||||
|                   <el-input size="small" v-model="formData.eastTo" placeholder="请输入" clearable maxlength="20"></el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="四至-南至"> | ||||
|                   <el-input size="small" v-model="formData.southTo" placeholder="请输入" clearable maxlength="20"></el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="四至-西至"> | ||||
|                   <el-input size="small" v-model="formData.westTo" placeholder="请输入" clearable maxlength="20"></el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="四至-北至"> | ||||
|                   <el-input size="small" v-model="formData.northTo" placeholder="请输入" clearable maxlength="20"></el-input> | ||||
|                 </el-form-item> | ||||
|               </div> | ||||
|               <el-form-item label="地类" class="buildingTypes"> | ||||
|                 <el-radio-group v-model="formData.landType"> | ||||
|                   <el-radio :label="item.dictValue" v-for="(item, index) in dict.getDict('homesteadLandType')" :key="index">{{item.dictName}}</el-radio> | ||||
|                 </el-radio-group> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="性质" class="buildingTypes"> | ||||
|                 <el-radio-group v-model="formData.houseType"> | ||||
|                   <el-radio :label="item.dictValue" v-for="(item, index) in dict.getDict('homesteadHouseType')" :key="index">{{item.dictName}}</el-radio> | ||||
|                 </el-radio-group> | ||||
|               </el-form-item> | ||||
|               <div class="flex"> | ||||
|                 <el-form-item label="住宅建筑面积"> | ||||
|                   <el-input size="small" v-model="formData.liveBuildingArea" placeholder="请输入" clearable maxlength="10"> | ||||
|                     <template slot="append">m²</template> | ||||
|                   </el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="建筑层数"> | ||||
|                   <el-input size="small" v-model="formData.buildingFloorNumber" placeholder="请输入" clearable maxlength="10"> | ||||
|                     <template slot="append">层</template> | ||||
|                   </el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="建筑高度"> | ||||
|                   <el-input size="small" v-model="formData.buildingHeight" placeholder="请输入" clearable maxlength="10"> | ||||
|                     <template slot="append">m</template> | ||||
|                   </el-input> | ||||
|                 </el-form-item> | ||||
|               </div> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card title="位置信息" > | ||||
|             <template slot="content"> | ||||
|               <div class="flex"> | ||||
|                 <el-form-item label="楼栋经度"> | ||||
|                   <el-input size="small" v-model="formData.lng" placeholder="请输入" clearable maxlength="10"></el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="楼栋纬度"> | ||||
|                   <el-input size="small" v-model="formData.lat" placeholder="请输入" clearable maxlength="10"></el-input> | ||||
|                 </el-form-item> | ||||
|               </div> | ||||
|               <el-form-item label="地图位置"> | ||||
|                 <el-button @click="showMap = true">地图标绘</el-button> | ||||
|               </el-form-item> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|         </el-form> | ||||
|       </template> | ||||
|       <!-- 底部按钮 --> | ||||
|       <template #footer> | ||||
|         <el-button @click="cancel">取消</el-button> | ||||
|         <el-button type="primary" @click="confirm()">提交</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|     <ai-dialog title="地图" :visible.sync="showMap" @opened="getCorpLocation" width="800px" class="mapDialog" @onConfirm="selectMap"> | ||||
|       <div id="map"></div> | ||||
|       <el-form label-width="80px" style="padding: 10px 20px 0 20px;"> | ||||
|         <el-row type="flex" justify="space-between"> | ||||
|           <el-form-item label="经度"> | ||||
|             <el-input disabled size="small" v-model="placeDetail.lng"></el-input> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="纬度"> | ||||
|             <el-input disabled size="small" v-model="placeDetail.lat"></el-input> | ||||
|           </el-form-item> | ||||
|         </el-row> | ||||
|       </el-form> | ||||
|       <el-input id="searchPlaceInput" size="medium" class="searchPlaceInput" clearable v-model="searchPlace" autocomplete="on" @change="placeSearch.search(searchPlace)" placeholder="请输入关键字"> | ||||
|         <el-button type="primary" slot="append" @click="placeSearch.search(searchPlace)">搜索</el-button> | ||||
|       </el-input> | ||||
|       <div id="searchPlaceOutput" /> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from 'vuex' | ||||
| import AMapLoader from '@amap/amap-jsapi-loader' | ||||
|  | ||||
| export default { | ||||
|   name: 'Add', | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     instance: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       formData: { | ||||
|         name: '', | ||||
|         idNumber: '', | ||||
|         age: '', | ||||
|         sex: '', | ||||
|         phone: '', | ||||
|         areaId: '', | ||||
|         homesteadArea: '', | ||||
|         houseArea: '', | ||||
|         homesteadAddress: '', | ||||
|         eastTo: '', | ||||
|         southTo: '', | ||||
|         westTo: '', | ||||
|         northTo: '', | ||||
|         landType: '0', | ||||
|         houseType: '0', | ||||
|         liveBuildingArea: '', | ||||
|         buildingFloorNumber: '', | ||||
|         buildingHeight: '', | ||||
|         lng: '', | ||||
|         lat: '', | ||||
|         id: '', | ||||
|         areaName: '' | ||||
|       }, | ||||
|       formRules: { | ||||
|         name: [ | ||||
|           { required: true, message: '请选择人员', trigger: 'change' }, | ||||
|         ], | ||||
|         age: [ | ||||
|           { required: true, message: '请输入年龄', trigger: 'change' }, | ||||
|         ], | ||||
|         sex: [ | ||||
|           { required: true, message: '请选择性别', trigger: 'change' }, | ||||
|         ], | ||||
|         idNumber: [ | ||||
|           { required: true, message: '请输入身份证号码', trigger: 'change' }, | ||||
|         ], | ||||
|         areaId: [ | ||||
|           { required: true, message: '请选择所属村', trigger: 'change' }, | ||||
|         ] | ||||
|       }, | ||||
|       map: null, | ||||
|       placeDetail: { | ||||
|         lng: '', | ||||
|         lat: '', | ||||
|       }, | ||||
|       showMap: false, | ||||
|       searchPlace: '', | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     isEdit() { | ||||
|       return !!this.params.id | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.dict.load('homesteadLocationStatus', 'homesteadHouseType', 'homesteadLandType', 'sex').then(() => { | ||||
|       if(this.params.id) { | ||||
|         this.getListinfo() | ||||
|       } | ||||
|     }) | ||||
|  | ||||
|   }, | ||||
|   methods: { | ||||
|     checkName(e) { | ||||
|       this.formData.name = e.name | ||||
|       this.formData.idNumber = e.idNumber | ||||
|       this.formData.phone = e.phone | ||||
|       this.formData.areaId = e.householdAreaId | ||||
|     }, | ||||
|     IdCard(UUserCard) { | ||||
|       if (UUserCard) { | ||||
|         let arr = []; | ||||
|         if (parseInt(UUserCard.substr(16, 1)) % 2 == 1) { | ||||
|           arr.push("1"); | ||||
|         } else { | ||||
|           arr.push("0"); | ||||
|         } | ||||
|  | ||||
|         const myDate = new Date(); | ||||
|         const month = myDate.getMonth() + 1; | ||||
|         const day = myDate.getDate(); | ||||
|         let age = myDate.getFullYear() - UUserCard.substring(6, 10) - 1; | ||||
|         if ( | ||||
|             UUserCard.substring(10, 12) < month || | ||||
|             (UUserCard.substring(10, 12) == month && | ||||
|                 UUserCard.substring(12, 14) <= day) | ||||
|         ) { | ||||
|           age++; | ||||
|         } | ||||
|         arr.push(age); | ||||
|         this.formData.sex = arr[0]; | ||||
|         this.formData.age = arr[1]; | ||||
|       } | ||||
|     }, | ||||
|     decimalInput(name) { | ||||
|       if(!/^(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/g.test(this.formData[name])){ | ||||
|         this.formData[name] = '' | ||||
|         return this.$message.error('最多只保留两位小数点') | ||||
|       } | ||||
|     }, | ||||
|     numberInput(name) { | ||||
|       if(!/^[1-9]\d*|0$/g.test(this.formData[name])){ | ||||
|         this.formData[name] = '' | ||||
|         return this.$message.error('请输入正整数') | ||||
|       } | ||||
|     }, | ||||
|     selectMap() { | ||||
|       this.formData.lng = this.placeDetail.lng | ||||
|       this.formData.lat = this.placeDetail.lat | ||||
|       this.showMap = false | ||||
|     }, | ||||
|     getCorpLocation() { | ||||
|       this.instance.post('/app/appdvcpconfig/getCorpLocation').then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.initMap(res.data) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     initMap({ lng, lat }) { | ||||
|       AMapLoader.load({ | ||||
|         key: '54a02a43d9828a8f9cd4f26fe281e74e', | ||||
|         version: '2.0', | ||||
|         plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete', 'AMap.Geocoder'], | ||||
|       }).then((AMap) => { | ||||
|         this.placeDetail.lng = this.formData.lng | ||||
|         this.placeDetail.lat = this.formData.lat | ||||
|         this.map = new AMap.Map('map', { | ||||
|           resizeEnable: true, | ||||
|           zooms: [6, 20], | ||||
|           center: [lng, lat], | ||||
|           zoom: 11, | ||||
|         }) | ||||
|         this.placeSearch = new AMap.PlaceSearch({ map: this.map }) | ||||
|         new AMap.AutoComplete({ | ||||
|           input: 'searchPlaceInput', | ||||
|           output: 'searchPlaceOutput', | ||||
|         }).on('select', (e) => { | ||||
|           if (e?.poi) { | ||||
|             this.placeSearch.setCity(e.poi.adcode) | ||||
|             this.movePosition(e.poi.location) | ||||
|           } | ||||
|         }) | ||||
|         this.map.on('click', (e) => { | ||||
|           new AMap.Geocoder().getAddress(e.lnglat, (sta, res) => { | ||||
|             if (res?.regeocode) { | ||||
|               this.placeDetail = { | ||||
|                 lng: e.lnglat?.lng, | ||||
|                 lat: e.lnglat?.lat, | ||||
|                 address: res.regeocode.formattedAddress, | ||||
|               } | ||||
|             } | ||||
|           }) | ||||
|           this.movePosition(e.lnglat) | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     movePosition(center) { | ||||
|       if (this.map) { | ||||
|         this.map.clearMap() | ||||
|         this.map.panTo(center) | ||||
|         this.map.add([ | ||||
|           new AMap.Marker({ | ||||
|             position: center, | ||||
|             clickable: true, | ||||
|           }), | ||||
|         ]) | ||||
|         this.map.setFitView() | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     getListinfo() { | ||||
|       return this.instance | ||||
|         .post('/app/apphomesteadinfo/queryDetailById', null, { | ||||
|           params: { | ||||
|             id: this.params.id, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res.data) { | ||||
|             this.formData = res.data | ||||
|           } | ||||
|         }) | ||||
|     }, | ||||
|  | ||||
|     confirm() { | ||||
|       this.$refs['ruleForm'].validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.instance | ||||
|             .post(`/app/apphomesteadinfo/addOrUpdate`, { | ||||
|               ...this.formData, | ||||
|             }) | ||||
|             .then((res) => { | ||||
|               if (res.code == 0) { | ||||
|                 this.$message.success('提交成功') | ||||
|                 setTimeout(() => { | ||||
|                   this.cancel(true) | ||||
|                 }, 1000) | ||||
|               } | ||||
|             }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 返回按钮 | ||||
|     cancel(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: !!isRefresh, | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     communityNameContent: { | ||||
|       deep: true, | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .Add { | ||||
|   height: 100%; | ||||
|   .ai-detail__title { | ||||
|     background-color: #fff; | ||||
|   } | ||||
|   .ai-detail__content { | ||||
|     .ai-detail__content--wrapper { | ||||
|       .el-form { | ||||
|         // background-color: #fff; | ||||
|         // padding: 0 60px; | ||||
|         .flex { | ||||
|           display: flex; | ||||
|           flex-wrap: wrap; | ||||
|           justify-content: space-between; | ||||
|           .el-form-item { | ||||
|             width: 48%; | ||||
|           } | ||||
|           .buildingTypes { | ||||
|             width: 100%; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .user-selecter { | ||||
|     ::v-deep .el-input-group__append { | ||||
|       width: 68px; | ||||
|       background: transparent; | ||||
|     } | ||||
|  | ||||
|     ::v-deep .el-button { | ||||
|       color: #fff; | ||||
|  | ||||
|       &:hover { | ||||
|         opacity: 0.8; | ||||
|         background: linear-gradient(90deg, #299FFF 0%, #0C61FF 100%); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| ::v-deep .mapDialog { | ||||
|   .el-dialog__body { | ||||
|     padding: 0; | ||||
|  | ||||
|     .ai-dialog__content { | ||||
|       padding: 0; | ||||
|     } | ||||
|  | ||||
|     .ai-dialog__content--wrapper { | ||||
|       padding: 0 !important; | ||||
|       position: relative; | ||||
|     } | ||||
|  | ||||
|     #map { | ||||
|       width: 100%; | ||||
|       height: 420px; | ||||
|     } | ||||
|  | ||||
|     .searchPlaceInput { | ||||
|       position: absolute; | ||||
|       width: 250px; | ||||
|       top: 30px; | ||||
|       left: 25px; | ||||
|     } | ||||
|  | ||||
|     #searchPlaceOutput { | ||||
|       position: absolute; | ||||
|       width: 250px; | ||||
|       left: 25px; | ||||
|       height: initial; | ||||
|       top: 80px; | ||||
|       background: white; | ||||
|       z-index: 250; | ||||
|       max-height: 300px; | ||||
|       overflow-y: auto; | ||||
|  | ||||
|       .auto-item { | ||||
|         text-align: left; | ||||
|         font-size: 14px; | ||||
|         padding: 8px; | ||||
|         box-sizing: border-box; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										203
									
								
								packages/2.0.5/AppHomesteadManagement/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								packages/2.0.5/AppHomesteadManagement/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| <template> | ||||
|   <section class="AppPetitionManage"> | ||||
|     <ai-list> | ||||
|       <!-- 标题 --> | ||||
|       <ai-title slot="title" title="宅基地管理" isShowBottomBorder  isShowArea v-model="areaId" :instance="instance" @change="page.current=1,getList()"/> | ||||
|       <template #content> | ||||
|         <ai-search-bar bottomBorder> | ||||
|           <template slot="left"> | ||||
|             <!-- 定位状态 --> | ||||
|             <ai-select v-model="search.locationStatus" placeholder="定位状态" clearable :selectList="$dict.getDict('homesteadLocationStatus')" @change=";(page.current = 1), getList()"></ai-select> | ||||
|           </template> | ||||
|  | ||||
|           <!-- 搜索 --> | ||||
|           <template slot="right"> | ||||
|             <el-input v-model="search.name" size="small" placeholder="户主/联系电话" clearable @keyup.enter.native=";(page.current = 1), getList()" @clear=";(page.current = 1), (search.name = ''), getList()" suffix-icon="iconfont iconSearch" /> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|  | ||||
|         <ai-search-bar class="ai-search-ba mar-t10"> | ||||
|           <template slot="left"> | ||||
|             <el-button icon="iconfont iconAdd" type="primary" size="small" @click="onAdd('')">添加 </el-button> | ||||
|             <el-button icon="iconfont iconDelete" size="small" @click="removeAll" :disabled="ids.length == 0">删除 </el-button> | ||||
|           </template> | ||||
|  | ||||
|           <!-- 导入导出 --> | ||||
|           <template #right> | ||||
|             <ai-import :instance="instance" :dict="dict" type="apphomesteadinfo" :importParams="{ areaId: user.info && user.info.areaId }" name="宅基地管理" @success="getList()"> | ||||
|               <el-button icon="iconfont iconImport">导入</el-button> | ||||
|             </ai-import> | ||||
|             <ai-download :instance="instance" url="/app/apphomesteadinfo/export" :params="param" fileName="宅基地管理模板" :disabled="tableData.length == 0"> | ||||
|               <el-button icon="iconfont iconExported" :disabled="tableData.length == 0">导出</el-button> | ||||
|             </ai-download> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|  | ||||
|         <ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" ref="aitableex" :current.sync="page.current" :size.sync="page.size" @getList="getList" @selection-change="(v) => (ids = v.map((e) => e.id))"> | ||||
|           <el-table-column slot="locationStatus" label="定位状态" align="center"> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <span style="color:red" v-if="row.locationStatus == 0">{{ dict.getLabel('homesteadLocationStatus', row.locationStatus) }}</span> | ||||
|               <span style="color:green" v-if="row.locationStatus == 1">{{ dict.getLabel('homesteadLocationStatus', row.locationStatus) }}</span> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|  | ||||
|           <el-table-column slot="options" label="操作" align="center" width="180" fixed="right"> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <el-button type="text" @click="onAdd(row.id)">编辑</el-button> | ||||
|               <el-button type="text" @click="remove(row.id)">删除</el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'List', | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     instance: Function, | ||||
|     params: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       isAdd: false, | ||||
|       page: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|       }, | ||||
|       total: 0, | ||||
|       search: { | ||||
|         locationStatus: '', | ||||
|         name: '', | ||||
|       }, | ||||
|       id: '', | ||||
|       ids: [], | ||||
|       colConfigs: [ | ||||
|         { type: 'selection', width: 100,  align: 'center'}, | ||||
|         { | ||||
|           prop: 'areaName', | ||||
|           label: '村/社区', | ||||
|         }, | ||||
|         { | ||||
|           prop: 'name', | ||||
|           label: '户主', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         { prop: 'phone', label: '联系电话', align: 'center' }, | ||||
|         { | ||||
|           prop: 'sex', | ||||
|           label: '性别', | ||||
|           width: '100', | ||||
|           align: 'center', | ||||
|           render: (h, { row }) => { | ||||
|             return h('span', null, this.dict.getLabel('sex', row.sex)) | ||||
|           }, | ||||
|         }, | ||||
|         { prop: 'age', label: '年龄', align: 'center' }, | ||||
|         { | ||||
|           prop: 'idNumber', | ||||
|           label: '身份证号', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         { prop: 'liveBuildingArea', label: '建筑面积(m²)', align: 'center',width: 120 }, | ||||
|         { | ||||
|           slot: 'locationStatus' | ||||
|         }, | ||||
|         { | ||||
|           slot: 'options', | ||||
|           label: '操作', | ||||
|           align: 'center', | ||||
|         }, | ||||
|       ], | ||||
|       tableData: [], | ||||
|       areaId: '', | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     param() { | ||||
|       return { | ||||
|         ...this.search, | ||||
|         areaId: this.user.info?.areaId, | ||||
|         ids: this.ids, | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     this.areaId = this.user.info.areaId | ||||
|     this.dict.load('homesteadLocationStatus', 'homesteadHouseType', 'homesteadLandType', 'sex').then(() => { | ||||
|       this.getList() | ||||
|     }) | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getList() { | ||||
|       this.instance | ||||
|         .post(`/app/apphomesteadinfo/list`, null, { | ||||
|           params: { | ||||
|             ...this.page, | ||||
|             ...this.search, | ||||
|             areaId: this.areaId, | ||||
|           }, | ||||
|         }) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             if(res.data.records.length) { | ||||
|               res.data.records.map((item) => { | ||||
|                 item.idNumber = item.idNumber.substring(0,10) +  '****' + item.idNumber.substring(13,17) | ||||
|               }) | ||||
|             } | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|     }, | ||||
|  | ||||
|     // 添加 | ||||
|     onAdd(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'add', | ||||
|         params: { | ||||
|           id: id || '', | ||||
|           areaId: this.areaId, | ||||
|         }, | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 删除 | ||||
|     remove(id) { | ||||
|       this.$confirm('确定删除该数据?').then(() => { | ||||
|         this.instance.post(`/app/apphomesteadinfo/delete?ids=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('删除成功!') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     removeAll() { | ||||
|       var id = this.ids.join(',') | ||||
|       this.remove(id) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppPetitionManage { | ||||
|   height: 100%; | ||||
|   .mar-t10{ | ||||
|     margin-top: 10px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										1342
									
								
								packages/2.0.5/AppHouseMap/AppHouseMap.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1342
									
								
								packages/2.0.5/AppHouseMap/AppHouseMap.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1429
									
								
								packages/2.0.5/AppHouseMap/AppPopulationDV.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1429
									
								
								packages/2.0.5/AppHouseMap/AppPopulationDV.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										443
									
								
								packages/2.0.5/AppHouseMap/buildingStatistics.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								packages/2.0.5/AppHouseMap/buildingStatistics.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,443 @@ | ||||
| <template> | ||||
|   <section class="buildingStatistics"> | ||||
|     <ai-title v-if="!isFormDv" title="楼栋统计" isShowBack isShowBottomBorder @onBackClick="$router.push({query:{}}),$parent.info={},$parent.isShowInfo=false,$parent.house=null,$parent.chooseBuildId='',$parent.showStatistics=false, $parent.type='0'"/> | ||||
|     <div class="buildingPane"> | ||||
|       <div class="bgItem tree"/> | ||||
|         <div class="building"> | ||||
|           <template v-if="floorRooms.length>0"> | ||||
|             <div class="buildingSignboard">{{ `${currentBuilding.buildingNumber}栋 ${unitNumber}单元` }} | ||||
|             </div> | ||||
|             <el-scrollbar class="floors"> | ||||
|               <div class="floor" v-for="(fl,j) in floorRooms" :key="j"> | ||||
|                 <div class="room" v-for="(op,i) in fl" :key="op.id" @click="handleSelectRoom(op,$event)" @touchstart="handleSelectRoom(op,$event)" :class="[{none:op.livingNumber==0,selected:selected.houseCode==op.houseCode},handleTipsHighlight(op.tips)]"> | ||||
|                   {{ op.houseCode }} | ||||
|                   <div v-if="op.livingNumber==0">无人</div> | ||||
|                   <div v-show="op.id==selected.id" class="detail" @click.stop :style="{left:position.x,top:position.y}"> | ||||
|                     <el-row class="popupHeader" type="flex" justify="space-between" align="middle"> | ||||
|                       <span>{{selected.houseCode}}详情</span> | ||||
|                       <ai-icon icon="iconClean" @click.native.stop="selected={}"/> | ||||
|                     </el-row> | ||||
|                     <div class="family-member"> | ||||
|                       <h2>房主信息</h2> | ||||
|                       <div v-for="(item,index) in selected.owner" :key="item.id"> | ||||
|                         <div class="family-member__item"> | ||||
|                           <div class="member-left"> | ||||
|                             <label>{{item.name}}</label> | ||||
|                           </div> | ||||
|                           <span style="color: #2266FF">{{root.dict.getLabel("houseLivingType",item.livingType)}}</span> | ||||
|                         </div> | ||||
|                         <div class="family-member__item"> | ||||
|                           <div class="member-left"> | ||||
|                             <label>联系方式</label> | ||||
|                           </div> | ||||
|                           <span style="color: #2266FF;">{{item.phone}}</span> | ||||
|                         </div> | ||||
|                       </div> | ||||
|  | ||||
|                       <h2>承租人信息</h2> | ||||
|                       <div v-for="(item,index) in selected.renter" :key="item.id"> | ||||
|                         <div class="family-member__item" > | ||||
|                           <div class="member-left"> | ||||
|                             <label>{{item.name}}</label> | ||||
|                           </div> | ||||
|                           <span style="color: #2266FF">{{root.dict.getLabel("houseLivingType",item.livingType)}}</span> | ||||
|                         </div> | ||||
|                         <div class="family-member__item"> | ||||
|                           <div class="member-left"> | ||||
|                             <label>联系方式</label> | ||||
|                           </div> | ||||
|                           <span>{{item.phone}}</span> | ||||
|                         </div> | ||||
|                       </div> | ||||
|  | ||||
|                       <h2>实际居住人员</h2> | ||||
|                       <div v-for="(item,index) in selected.live" :key="item.id"> | ||||
|                         <div class="family-member__item"> | ||||
|                           <div class="member-left"> | ||||
|                             <label>{{item.name}}</label> | ||||
|                           </div> | ||||
|                           <span>{{root.dict.getLabel("householdRelation",item.relation)}}</span> | ||||
|                         </div> | ||||
|                       </div> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </el-scrollbar> | ||||
|           </template> | ||||
|           <ai-empty v-else>请在【<b>小区总览</b>】中选取【楼栋单元】</ai-empty> | ||||
|           <div class="bottom"/> | ||||
|         </div> | ||||
|       <building-tool-bar></building-tool-bar> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import BuildingToolBar from "./buildingToolBar"; | ||||
|  | ||||
| export default { | ||||
|   name: "buildingStatistics", | ||||
|   components: {BuildingToolBar}, | ||||
|   inject: ['root'], | ||||
|   provide() { | ||||
|     return { | ||||
|       sta: this | ||||
|     } | ||||
|   }, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     isFormDv: Boolean, | ||||
|     query: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       rooms: [], | ||||
|       selected: {}, | ||||
|       currentBuilding: {}, | ||||
|       unitNumber:1, | ||||
|       tips: [], | ||||
|       position:{ | ||||
|         x:"", | ||||
|         y:"" | ||||
|       }, | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     floorRooms() { | ||||
|       let obj = {} | ||||
|       this.rooms.map(e => { | ||||
|         e.none = e.isNone == 0 | ||||
|         return obj[e.layerNumber]?.push(e) || (obj[e.layerNumber] = [e]) | ||||
|       }) | ||||
|       return Object.values(obj).reverse() | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load('householdRelation', 'residentTipType',"houseLivingType") | ||||
|     if (this.isFormDv && this.query.buildingId) { | ||||
|       this.getRoomsByBuilding(this.query.buildingId, this.query.unitNum) | ||||
|       this.currentBuilding = { buildingNumber: this.query.buildingNumber} | ||||
|       this.unitNumber = this.query.unitNum | ||||
|  | ||||
|       return false | ||||
|     } | ||||
|     this.getRoomsByBuilding(this.$route.query?.buildingId,this.$route.query?.unitNum) | ||||
|     this.currentBuilding = {buildingNumber: this.$route.query?.buildingNumber}; | ||||
|     this.unitNumber = this.$route.query?.unitNum; | ||||
|   }, | ||||
|   methods: { | ||||
|     handleSelectRoom(room, e) { | ||||
|       console.log(e) | ||||
|       if (room.livingNumber>0) { | ||||
|         this.$nextTick(()=>{ | ||||
|           this.position.x = e.pageX + 40 + "px" | ||||
|           this.position.y = e.pageY + "px" | ||||
|           this.selected = room; | ||||
|           this.$forceUpdate() | ||||
|         }) | ||||
|         // this.getRoomDetail(room.id) | ||||
|       } | ||||
|     }, | ||||
|     selectedBuilding(building,unitNumber) { | ||||
|       this.selected = {} | ||||
|       this.tips = [] | ||||
|       this.$router.push({query: {...this.$route.query, buildingId: building.id,unitNum:unitNumber}}).catch(e=>{e}) | ||||
|       this.currentBuilding = building | ||||
|       this.unitNumber = unitNumber | ||||
|       this.getRoomsByBuilding(building.id,unitNumber) | ||||
|     }, | ||||
|     getRoomsByBuilding(buildingId,unitNumber) { | ||||
|       this.root.instance.post("/app/appcommunityhouseinfo/list", null, { | ||||
|         params: { | ||||
|           unitNumber, | ||||
|           buildingId, | ||||
|           size: 999 | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.rooms = res.data.records | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getRoomDetail(id) { | ||||
|       return this.root.instance.post("/app/appcommunityhouseinfo/queryDetailById", null, { | ||||
|         params: {id} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           let {residents} = res.data | ||||
|           this.selected = { | ||||
|             ...this.selected, ...res.data, | ||||
|             residents: residents.map(e => { | ||||
|               let {tips} = e | ||||
|               //显示为户主 | ||||
|               let relationLabel = e.householdName == 1 ? "户主" : this.root.dict.getLabel("householdRelation", e.householdRelation) | ||||
|               return {...e, tips: tips ? tips.split("|") : [], relationLabel} | ||||
|             } | ||||
|             ) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleTipsHighlight(tip) { | ||||
|       let flag = this.tips.length > 0 && !this.tips.some(t => tip?.split("|").includes(t)) | ||||
|       return flag ? 'tipsHighlight' : '' | ||||
|     }, | ||||
|     selectedTips(tips) { | ||||
|       this.tips = tips | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .buildingStatistics { | ||||
|   height: 100%; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|  | ||||
|   ::v-deep .ailist-title{ | ||||
|     margin: 0 20px; | ||||
|   } | ||||
|  | ||||
|   .family-member { | ||||
|     & > h2 { | ||||
|       height: 32px; | ||||
|       line-height: 32px; | ||||
|       margin: 0; | ||||
|       padding: 0 12px; | ||||
|       color: #333333; | ||||
|       font-size: 12px; | ||||
|       font-weight: 700; | ||||
|       text-align: left; | ||||
|       background: #E3E8F1; | ||||
|     } | ||||
|  | ||||
|     .family-member__item { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
|       height: 32px; | ||||
|       padding: 0 12px; | ||||
|       background: #F3F6F9; | ||||
|  | ||||
|       .member-left { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         gap: 4px; | ||||
|       } | ||||
|  | ||||
|       &:nth-of-type(2n) { | ||||
|         background: #fff; | ||||
|       } | ||||
|  | ||||
|       label { | ||||
|         font-weight: normal !important; | ||||
|         color: #333; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|  | ||||
|       & > span { | ||||
|         color: #666666; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     &:last-child { | ||||
|       label { | ||||
|         color: #666666; | ||||
|         font-weight: normal !important; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .buildingPane { | ||||
|     background-image: url("https://cdn.cunwuyun.cn/buildSta/cloud.png"), linear-gradient(3deg, #FFFFFF 0%, #3093FF 100%); | ||||
|     background-repeat: no-repeat; | ||||
|     background-position: 227px 43px, 100%; | ||||
|     background-size: 788px 112px, 100%; | ||||
|     position: relative; | ||||
|     box-sizing: border-box; | ||||
|     padding-right: 400px; | ||||
|     flex: 1; | ||||
|     min-height: 0; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     justify-content: flex-end; | ||||
|     align-items: flex-start; | ||||
|  | ||||
|     .bgItem { | ||||
|       position: absolute; | ||||
|       background-repeat: no-repeat; | ||||
|       pointer-events: none; | ||||
|  | ||||
|       &.tree { | ||||
|         left: calc(50% - 200px); | ||||
|         transform: translateX(-50%); | ||||
|         bottom: 0; | ||||
|         width: 580px; | ||||
|         height: 71px; | ||||
|         background-image: url("https://cdn.cunwuyun.cn/buildSta/tree.png"); | ||||
|         z-index: 3; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .building { | ||||
|       margin-left: 60px; | ||||
|       flex-shrink: 0; | ||||
|       height: auto; | ||||
|       width: auto; | ||||
|       box-sizing: border-box; | ||||
|       padding: 136px 0 0; | ||||
|       background-image: url("https://cdn.cunwuyun.cn/buildSta/roof.png"), | ||||
|       url("https://cdn.cunwuyun.cn/buildSta/chimney.png"); | ||||
|       background-position: 0 121px, 70px 91px; | ||||
|       background-size: 100% 105px, 70px; | ||||
|       background-repeat: no-repeat; | ||||
|       display: flex; | ||||
|       flex-direction: column; | ||||
|       justify-content: flex-end; | ||||
|       align-items: center; | ||||
|       border-bottom: 10px solid #E9C28E; | ||||
|  | ||||
|       .buildingSignboard { | ||||
|         padding-top: 41px; | ||||
|         width: 200px; | ||||
|         height: 65px; | ||||
|         text-align: center; | ||||
|         background-image: url("https://cdn.cunwuyun.cn/buildSta/buildingSignboard.png"); | ||||
|         background-repeat: no-repeat; | ||||
|         box-sizing: border-box; | ||||
|         font-size: 12px; | ||||
|         font-weight: bold; | ||||
|         color: #1D3296; | ||||
|         margin-bottom: 15px; | ||||
|       } | ||||
|  | ||||
|       .ai-empty { | ||||
|         background: #FFECD9; | ||||
|         margin: 90px 20px 0; | ||||
|         padding: 0 10px 90px; | ||||
|         font-size: 14px; | ||||
|         color: #666; | ||||
|  | ||||
|         b { | ||||
|           color: #26f | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .bottom { | ||||
|         background: #FFECD9; | ||||
|         height: 50px; | ||||
|         width: calc(100% - 40px); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     ::v-deep .floors { | ||||
|       max-height: 520px; | ||||
|  | ||||
|       .el-scrollbar__wrap { | ||||
|         overflow-x: hidden; | ||||
|         margin-bottom: 0 !important; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .floor { | ||||
|       margin: 0 20px; | ||||
|       height: 105px; | ||||
|       flex-shrink: 0; | ||||
|       max-width: calc(100% - 40px); | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       background-image: url("https://cdn.cunwuyun.cn/buildSta/floor.png"); | ||||
|       background-size: 100% 105px; | ||||
|       padding: 0 30px; | ||||
|       box-sizing: border-box; | ||||
|       gap: 20px; | ||||
|  | ||||
|       .room { | ||||
|         width: 60px; | ||||
|         height: 72px; | ||||
|         background-image: url("https://cdn.cunwuyun.cn/buildSta/room.png"); | ||||
|         text-align: center; | ||||
|         padding-top: 20px; | ||||
|         box-sizing: border-box; | ||||
|         font-size: 14px; | ||||
|         font-weight: bold; | ||||
|         color: #FFFFFF; | ||||
|         cursor: pointer; | ||||
|         position: relative; | ||||
|  | ||||
|         .detail { | ||||
|           position: fixed; | ||||
|           width: 320px; | ||||
|           background: #fff; | ||||
|           box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1); | ||||
|           border-radius: 4px; | ||||
|           overflow: hidden; | ||||
|           display: flex; | ||||
|           flex-direction: column; | ||||
|           z-index: 11; | ||||
|           transform: translateY(-100%); | ||||
|  | ||||
|           .popupHeader { | ||||
|             background: #D42222; | ||||
|             padding: 0 12px; | ||||
|             height: 32px; | ||||
|  | ||||
|             .AiIcon { | ||||
|               width: 16px; | ||||
|               height: 16px; | ||||
|             } | ||||
|           } | ||||
|  | ||||
|           li { | ||||
|             list-style-type: none; | ||||
|             display: flex; | ||||
|             justify-content: space-between; | ||||
|             align-items: center; | ||||
|             padding: 0 12px; | ||||
|             font-size: 12px; | ||||
|             color: #333; | ||||
|             height: 32px; | ||||
|  | ||||
|             & > div { | ||||
|  | ||||
|             } | ||||
|  | ||||
|             &.title { | ||||
|               background: #E3E8F1; | ||||
|             } | ||||
|  | ||||
|             &.stretch { | ||||
|               background: #F3F6F9; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         &.none { | ||||
|           cursor: not-allowed; | ||||
|           color: #f46; | ||||
|           background-image: url("https://cdn.cunwuyun.cn/buildSta/roomNone.png"); | ||||
|         } | ||||
|  | ||||
|         &.selected { | ||||
|           background-image: url("https://cdn.cunwuyun.cn/buildSta/roomSelected.png"); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .buildingToolBar { | ||||
|       position: absolute; | ||||
|       right: 20px; | ||||
|       top: 20px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .tipsHighlight { | ||||
|     opacity: 0.6; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										95
									
								
								packages/2.0.5/AppHouseMap/buildingToolBar.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								packages/2.0.5/AppHouseMap/buildingToolBar.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| <template> | ||||
|   <section class="buildingToolBar"> | ||||
|     <div class="toolBar"> | ||||
|       <div class="nav" v-for="(op,i) in navs" :key="i" :class="{selected:i==active}" @click="active=i"> | ||||
|         <ai-icon :icon="op.icon"/> | ||||
|         <div>{{ op.name }}</div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <component :is="currentNav.comp" class="toolPane"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import BuildingInfo from "./toolBar/buildingInfo"; | ||||
| import CommunityOverview from "./toolBar/communityOverview"; | ||||
| // import NearbyGCS from "./toolBar/nearbyGCS"; | ||||
| import RecentEvents from "./toolBar/recentEvents"; | ||||
|  | ||||
| export default { | ||||
|   name: "buildingToolBar", | ||||
|   components: {RecentEvents, CommunityOverview, BuildingInfo}, | ||||
|   computed: { | ||||
|     navs() { | ||||
|       return [ | ||||
|         {icon: 'icondanweiguanli', name: "单元统计", comp: BuildingInfo}, | ||||
|         {icon: 'icondanweiguanli', name: "单元切换", comp: CommunityOverview}, | ||||
|         // {icon: 'icondanweiguanli', name: "网格员", comp: NearbyGCS}, | ||||
|         // {icon: 'icondanweiguanli', name: "近期事件", comp: RecentEvents}, | ||||
|       ] | ||||
|     }, | ||||
|     currentNav() { | ||||
|       return this.navs[this.active] | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       active: 0 | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .buildingToolBar { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   gap: 10px; | ||||
|  | ||||
|   .toolBar { | ||||
|     height: 40px; | ||||
|     background: #FFFFFF; | ||||
|     box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2); | ||||
|     border-radius: 4px; | ||||
|     padding: 4px; | ||||
|     width: 400px; | ||||
|     display: flex; | ||||
|     gap: 8px; | ||||
|     box-sizing: border-box; | ||||
|     align-self: flex-end; | ||||
|  | ||||
|     .nav { | ||||
|       flex: 1; | ||||
|       height: 32px; | ||||
|       color: #3A3A3A; | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: center; | ||||
|       font-size: 12px; | ||||
|       cursor: pointer; | ||||
|  | ||||
|       .AiIcon { | ||||
|         width: 16px; | ||||
|         height: 16px; | ||||
|         margin-right: 4px; | ||||
|       } | ||||
|  | ||||
|       &:hover { | ||||
|         color: #2266FF; | ||||
|       } | ||||
|  | ||||
|       &.selected { | ||||
|         background: #E4F0FF; | ||||
|         color: #2266FF; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .toolPane { | ||||
|     background: #FFFFFF; | ||||
|     box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1); | ||||
|     border-radius: 4px; | ||||
|     overflow: hidden; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										249
									
								
								packages/2.0.5/AppHouseMap/toolBar/buildingInfo.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								packages/2.0.5/AppHouseMap/toolBar/buildingInfo.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | ||||
| <template> | ||||
|   <section class="buildingInfo"> | ||||
|     <ai-title title="人口信息"/> | ||||
|     <div class="infoPane"> | ||||
|       <div class="staZone"> | ||||
|         <div v-for="(value, name) in staData" :key="name"> | ||||
|           <b>{{ value }}</b> | ||||
|           <span>{{ name }}</span> | ||||
|         </div> | ||||
|       </div> | ||||
| <!--      <div id="PersonStaChart"/>--> | ||||
|       <div class="static-wrap"> | ||||
|         <div class="sta-item" v-for="(value,name) in tag" :key="name"> | ||||
|           <div class="sta-left"> | ||||
|             <em class="tag" :style="{backgroundColor:color[name]}"></em> | ||||
|             <label>{{name}}</label> | ||||
|           </div> | ||||
|           <span class="num">{{value}}</span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <ai-title title="房屋信息"/> | ||||
|     <div class="infoPane"> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>所属社区</span> | ||||
|         <span>{{build.areaName}}</span> | ||||
|       </el-row> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>所属小区</span> | ||||
|         <span>{{build.communityName}}</span> | ||||
|       </el-row> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>房屋类型</span> | ||||
|         <span>{{root.dict.getLabel("communityBuildingType",build.buildingType)}}</span> | ||||
|       </el-row> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>楼长姓名</span> | ||||
|         <span>{{build.managerName}}</span> | ||||
|       </el-row> | ||||
|       <el-row type="flex" justify="space-between" class="info-item"> | ||||
|         <span>联系方式</span> | ||||
|         <span>{{build.managerPhone}}</span> | ||||
|       </el-row> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import * as echarts from 'echarts' | ||||
|  | ||||
| export default { | ||||
|   name: "buildingInfo", | ||||
|   inject: ['root', 'sta'], | ||||
|   computed: { | ||||
|     chartData() { | ||||
|       return this.root.dict.getDict("residentTipType").map(e => ({ | ||||
|         name: e.dictName, | ||||
|         key: e.dictValue, | ||||
|         color: e.dictColor, | ||||
|         v1: 0 | ||||
|       })) | ||||
|     }, | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {prop:"areaName",label:"所属社区"} | ||||
|       ]; | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       chart: null, | ||||
|       staData: {}, | ||||
|       tag:{}, | ||||
|       color:{}, | ||||
|       build:{}, | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     initChart(data) { | ||||
|       this.chart = echarts.init(document.getElementById("PersonStaChart")) | ||||
|       let selected = {}, color = [] | ||||
|       this.chartData.map(e => { | ||||
|         selected[e.name] = false | ||||
|         color.push(e.color) | ||||
|       }) | ||||
|       this.chart.setOption({ | ||||
|         grid: {top: 31, right: 0, height: 135}, | ||||
|         tooltip: {}, | ||||
|         legend: { | ||||
|           top: 185, | ||||
|           left: 0, | ||||
|           orient: "vertical", | ||||
|           selected, | ||||
|           itemWidth: 14, | ||||
|           itemHeight: 14, | ||||
|           itemGap: 12, | ||||
|           icon: "rect", | ||||
|           formatter: name => { | ||||
|             let item = data.find(e => this.root.dict.getLabel('residentTipType', e.name) == name) | ||||
|             return `{a|${name}}  {b|${item.v1}}` | ||||
|           }, | ||||
|           textStyle: { | ||||
|             rich: { | ||||
|               a: {color: "#666", width: 123}, | ||||
|               b: {color: "#333", fontWeight: 'bold', align: 'right'} | ||||
|             } | ||||
|           } | ||||
|         }, color, | ||||
|         yAxis: {type: 'value', min: 0, minInterval: 1, axisTick: false, axisLine: false, axisLabel: {color: "#666"}}, | ||||
|         xAxis: {type: 'category', axisTick: false, axisLine: false, axisLabel: false}, | ||||
|         series: data.map(e => ({ | ||||
|           type: 'bar', | ||||
|           barWidth: 8, | ||||
|           barGap: '250%', | ||||
|           name: this.root.dict.getLabel('residentTipType', e.name) | ||||
|         })) | ||||
|       }) | ||||
|       this.chart.on('legendselectchanged', ({selected}) => { | ||||
|         let tips = Object.keys(selected)?.filter(e => selected[e])?.map(e => this.root.dict.getValue('residentTipType', e)) | ||||
|         this.sta?.selectedTips(tips) | ||||
|       }) | ||||
|       this.getChartData(data) | ||||
|     }, | ||||
|     getChartData(data) { | ||||
|       this.chart?.setOption({ | ||||
|         series: data.map(e => ({data: [e.v1]})) | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   created(){ | ||||
|     this.root.dict?.load("communityBuildingType") | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.root.instance.post("/app/appcommunitybuildinginfo/statistics", null, { | ||||
|       params: { | ||||
|         id: this.root.isFormDv ? this.root.info.id : this.$route.query.buildingId, | ||||
|         unitNum: this.root.isFormDv ? this.root.info.unitNumber : this.$route.query.unitNum, | ||||
|       } | ||||
|     }).then(res => { | ||||
|       if (res?.data) { | ||||
|         this.staData = res.data.unit; | ||||
|         this.tag = res.data.tag; | ||||
|         this.color = res.data.color; | ||||
|         this.build = res.data.build; | ||||
|         // this.root.dict.load('residentTipType').then(() => { | ||||
|         //   this.initChart(res.data.lx) | ||||
|         // }) | ||||
|       } | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .buildingInfo { | ||||
|   ::v-deep .infoPane { | ||||
|     box-sizing: border-box; | ||||
|     padding: 10px 20px; | ||||
|  | ||||
|     .info-item{ | ||||
|       height: 32px; | ||||
|       box-sizing: border-box; | ||||
|       padding: 0 12px; | ||||
|       font-size: 12px; | ||||
|       color: #666666; | ||||
|       align-items: center; | ||||
|  | ||||
|       span:last-child{ | ||||
|         color: #333333; | ||||
|       } | ||||
|  | ||||
|       &:nth-child(2n-1){ | ||||
|         background-color: #F3F6F9; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .static-wrap{ | ||||
|       width: 360px; | ||||
|       box-sizing: border-box; | ||||
|       padding-top: 20px; | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
|       flex-wrap: wrap; | ||||
|  | ||||
|       .sta-item{ | ||||
|         width: 46%; | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         justify-content: space-between; | ||||
|         margin-bottom: 8px; | ||||
|  | ||||
|         .sta-left{ | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           .tag{ | ||||
|             width: 14px; | ||||
|             height: 14px; | ||||
|             background: #DC1739; | ||||
|             border-radius: 2px; | ||||
|             margin-right: 3px; | ||||
|           } | ||||
|           & > label{ | ||||
|             font-size: 12px; | ||||
|             color: #666666; | ||||
|           } | ||||
|         } | ||||
|         .num{ | ||||
|           font-size: 12px; | ||||
|           color: #333333; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     .staZone { | ||||
|       height: 80px; | ||||
|       background: #F5F7F9; | ||||
|       border-radius: 4px; | ||||
|       overflow: hidden; | ||||
|       display: flex; | ||||
|  | ||||
|       & > div { | ||||
|         flex: 1; | ||||
|         min-width: 0; | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         justify-content: center; | ||||
|         align-items: center; | ||||
|         height: 100%; | ||||
|         font-size: 12px; | ||||
|         color: #333; | ||||
|  | ||||
|         b { | ||||
|           font-size: 24px; | ||||
|           font-family: DINAlternate-Bold, DINAlternate,serif; | ||||
|           color: #2266FF; | ||||
|           margin-bottom: 4px; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     #PersonStaChart { | ||||
|       width: 100%; | ||||
|       height: 350px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										116
									
								
								packages/2.0.5/AppHouseMap/toolBar/communityOverview.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								packages/2.0.5/AppHouseMap/toolBar/communityOverview.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| <template> | ||||
|   <section class="communityOverview"> | ||||
|     <ai-title title="小区总览"/> | ||||
|     <div class="units" v-if="Object.keys(buildingUnits).length>0"> | ||||
|       <div class="building" v-for="(value,name) in buildingUnits" :key="name"> | ||||
|         <div class="unit" v-for="(op,j) in value" :key="j" @click="sta.selectedBuilding(op,j+1)" | ||||
|              :class="{selected:sta.unitNumber==j+1 && sta.currentBuilding.buildingNumber==name}"> | ||||
|           <b>{{ name}}栋</b> | ||||
|           <div>{{ j+1 }}单元</div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <AiEmpty v-else>暂无楼栋信息,请进入【楼栋管理】添加</AiEmpty> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "communityOverview", | ||||
|   inject: ['root', 'sta'], | ||||
|   computed: { | ||||
|     buildingUnits() { | ||||
|       let obj = {} | ||||
|       this.units.map(e => { | ||||
|         for(let i=0;i<e.unitNumber;i++){ | ||||
|           obj[e.buildingNumber]?.push(e) || (obj[e.buildingNumber] = [e]) | ||||
|         } | ||||
|       }) | ||||
|       return obj; | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       units: [] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getUnits(communityId) { | ||||
|       this.root.instance.post("/app/appcommunitybuildinginfo/list", null, { | ||||
|         params: { | ||||
|           communityId, | ||||
|           size: 999 | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.units = res.data.records | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getUnits(this.root.isFormDv ? this.root.info.communityId : this.$route.query.communityId) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .communityOverview { | ||||
|   max-width: 400px; | ||||
|  | ||||
|   .units { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|     padding: 0 20px 20px; | ||||
|     align-items: flex-start; | ||||
|  | ||||
|     .building { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       height: auto; | ||||
|       flex-wrap: wrap;  | ||||
|  | ||||
|       .unit { | ||||
|         margin-right: 10px; | ||||
|         margin-bottom: 10px; | ||||
|  | ||||
|         &:nth-of-type(5) { | ||||
|           margin-right: 0; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .unit { | ||||
|       width: 64px; | ||||
|       height: 56px; | ||||
|       background: #F8FBFF; | ||||
|       border-radius: 2px 0 0 2px; | ||||
|       border: 1px solid #829CCF; | ||||
|       display: flex; | ||||
|       flex-direction: column; | ||||
|       justify-content: center; | ||||
|       align-items: center; | ||||
|       font-size: 12px; | ||||
|       color: #999; | ||||
|       cursor: pointer; | ||||
|  | ||||
|       b { | ||||
|         color: #424242; | ||||
|       } | ||||
|  | ||||
|       &.selected { | ||||
|         color: #fff; | ||||
|         background: #2266FF; | ||||
|  | ||||
|         b { | ||||
|           color: #fff; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .ai-empty { | ||||
|     height: 240px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										129
									
								
								packages/2.0.5/AppHouseMap/toolBar/nearbyGCS.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								packages/2.0.5/AppHouseMap/toolBar/nearbyGCS.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| <template> | ||||
|   <section class="nearbyGCS"> | ||||
|     <ai-title title="全部网格员"/> | ||||
|     <div class="radarPane"> | ||||
|       <div class="radar"> | ||||
|         <div class="indicator"/> | ||||
|       </div> | ||||
|       <div class="gcsItem" v-for="(op,i) in userList" :key="i" :style="op.style"> | ||||
|         <i class="dot" :class="{offline:op.offline}"/> | ||||
|         <span>{{ op.name }}</span> | ||||
|         <ai-icon icon="iconIM"/> | ||||
|       </div> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "nearbyGCS", | ||||
|   inject: ['root', 'sta'], | ||||
|  | ||||
|   data () { | ||||
|     return { | ||||
|       userList: [] | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   mounted () { | ||||
|     this.getInfo() | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getInfo () { | ||||
|       this.root.instance.post('/app/appgirdmemberinfo/queryGirdMemberByBuilding', null, { | ||||
|         params: {buildingId: this.$route.query.buildingId} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.gcsList(res.data) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     gcsList (data) { | ||||
|       this.userList = data.map(e => ({ | ||||
|         ...e, | ||||
|         style: { | ||||
|           transform: `translate( | ||||
|         ${Math.round(160 * (Math.random() - 0.5))}px, | ||||
|         ${Math.round(160 * (Math.random() - 0.5))}px)`} | ||||
|       })) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .nearbyGCS { | ||||
|   .radarPane { | ||||
|     width: 100%; | ||||
|     height: 360px; | ||||
|     display: flex; | ||||
|     justify-content: center; | ||||
|     align-items: center; | ||||
|     position: relative; | ||||
|  | ||||
|     .gcsItem { | ||||
|       position: absolute; | ||||
|       width: 92px; | ||||
|       height: 28px; | ||||
|       background: #FFFFFF; | ||||
|       box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); | ||||
|       border-radius: 16px; | ||||
|       font-size: 12px; | ||||
|       color: #333333; | ||||
|       display: flex; | ||||
|       justify-content: center; | ||||
|       align-items: center; | ||||
|       z-index: 3; | ||||
|       gap: 8px; | ||||
|  | ||||
|       .AiIcon { | ||||
|         width: 16px; | ||||
|         height: 16px; | ||||
|       } | ||||
|  | ||||
|       .dot { | ||||
|         width: 4px; | ||||
|         height: 4px; | ||||
|         background: #30BC77; | ||||
|  | ||||
|         &.offline { | ||||
|           background: #FF4466; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .radar { | ||||
|     width: 320px; | ||||
|     height: 320px; | ||||
|     position: relative; | ||||
|     border-radius: 50%; | ||||
|     overflow: hidden; | ||||
|     background-image: url("https://cdn.cunwuyun.cn/buildSta/radarBg.png"); | ||||
|  | ||||
|     .indicator { | ||||
|       position: absolute; | ||||
|       width: 160px; | ||||
|       height: 160px; | ||||
|       top: 0; | ||||
|       left: 0; | ||||
|       transform-origin: 100% 100%; | ||||
|       background: linear-gradient(190deg, rgba(162, 255, 182, 0.5) 0%, rgba(162, 255, 215, 0) 100%); | ||||
|       border-right: 1px solid #A2FFB6; | ||||
|       animation: radar 5s linear infinite; | ||||
|       z-index: 2; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @keyframes radar { | ||||
|   0% { | ||||
|     transform: rotate(0deg) | ||||
|   } | ||||
|   100% { | ||||
|     transform: rotate(360deg) | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										81
									
								
								packages/2.0.5/AppHouseMap/toolBar/recentEvents.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								packages/2.0.5/AppHouseMap/toolBar/recentEvents.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| <template> | ||||
|   <section class="recentEvents"> | ||||
|     <ai-title title="楼栋近期相关事件"/> | ||||
|     <div class="recentEvents-list"> | ||||
|       <div class="recentEvents-item" v-for="(item, index) in 4" :key="index"> | ||||
|         <div class="recentEvents-item__top"> | ||||
|           <i>[已解决]</i> | ||||
|           <span>102室与402室矛盾纠纷</span> | ||||
|         </div> | ||||
|         <div class="recentEvents-item__middle"> | ||||
|           <span>102室与402室矛盾纠纷</span> | ||||
|           <em>[张三]</em> | ||||
|           <span>接到了</span> | ||||
|           <em>[矛盾调解]</em> | ||||
|           <span>任务,事件目前</span> | ||||
|           <i>[已完成]</i> | ||||
|         </div> | ||||
|         <div class="recentEvent-item__bottom">2019-06-18 13:35:45</div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "recentEvents" | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .recentEvents { | ||||
|   font-size: 14px; | ||||
|   width: 100%; | ||||
|  | ||||
|   .recentEvents-list { | ||||
|     .recentEvents-item { | ||||
|       border-bottom: 1px solid #E6E8EE; | ||||
|       background: transparent; | ||||
|       padding: 10px; | ||||
|       box-sizing: border-box; | ||||
|       .recentEvent-item__bottom { | ||||
|         color: #999; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|  | ||||
|       &:first-child { | ||||
|         background: #EFF6FF; | ||||
|         border-bottom: none; | ||||
|       } | ||||
|  | ||||
|       &:last-child { | ||||
|         border-bottom: none; | ||||
|       } | ||||
|  | ||||
|       .recentEvents-item__top { | ||||
|         display: flex; | ||||
|       } | ||||
|  | ||||
|       .recentEvents-item__middle { | ||||
|         margin: 6px 0 10px; | ||||
|       } | ||||
|  | ||||
|       span { | ||||
|         color: #666666; | ||||
|       } | ||||
|  | ||||
|       em { | ||||
|         color: #2266FF; | ||||
|         font-style: normal; | ||||
|       } | ||||
|  | ||||
|       i { | ||||
|         font-style: normal; | ||||
|         color: #2EA222; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										61
									
								
								packages/2.0.5/AppMediaManage/AppMediaManage.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								packages/2.0.5/AppMediaManage/AppMediaManage.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| <template> | ||||
|   <div class="AppMediaManage"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from './components/List' | ||||
| import Add from './components/Add' | ||||
|  | ||||
| export default { | ||||
|   label: '媒资管理', | ||||
|   name: 'AppMediaManage', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: 'List', | ||||
|       params: {}, | ||||
|       include: [], | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     Add, | ||||
|     List | ||||
|   }, | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === 'add') { | ||||
|         this.component = 'Add' | ||||
|         this.params = data.params | ||||
|       } | ||||
|  | ||||
|       if (data.type == 'list') { | ||||
|         this.component = 'List' | ||||
|         this.params = data.params | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getList() | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppMediaManage { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										189
									
								
								packages/2.0.5/AppMediaManage/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								packages/2.0.5/AppMediaManage/components/Add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,189 @@ | ||||
| <template> | ||||
|   <section style="height: 100%"> | ||||
|     <ai-detail class="Add"> | ||||
|       <!-- 返回按钮 --> | ||||
|       <template #title> | ||||
|         <ai-title title="添加媒资信息" isShowBack isShowBottomBorder @onBackClick="cancel(false)"></ai-title> | ||||
|       </template> | ||||
|       <template #content> | ||||
|         <el-form :model="formData" :rules="formRules" ref="ruleForm" label-width="150px" label-suffix=":" align-items="center"> | ||||
|           <ai-bar title="基础信息"></ai-bar> | ||||
|           <div class="flex"> | ||||
|             <el-form-item label="媒资类型" prop="type" class="buildingTypes"> | ||||
|               <el-radio-group v-model="formData.type"> | ||||
|                 <el-radio label='1'>音频广播</el-radio> | ||||
|                 <el-radio label='3'>文本广播</el-radio> | ||||
|               </el-radio-group> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="媒资名称" prop="name" class="buildingTypes"> | ||||
|               <el-input size="small" v-model="formData.name" placeholder="请输入" maxlength="30" show-word-limit></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="文本内容" prop="content" class="buildingTypes" v-if="formData.type == 3"> | ||||
|               <el-input size="small"  type="textarea" :rows="2" v-model="formData.content" placeholder="请输入" maxlength="12000" show-word-limit></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="上传音频" prop="file" class="buildingTypes" v-if="formData.type == 1"> | ||||
|               <ai-uploader | ||||
|                   :isShowTip="true" | ||||
|                   :instance="instance" | ||||
|                   v-model="formData.file" | ||||
|                   fileType="file" | ||||
|                   acceptType=".mp3" | ||||
|                   :limit="1"> | ||||
|                 <template slot="tips">最多上传1个附件,单个文件最大10MB<br/>支持.mp3格式 | ||||
|                 </template> | ||||
|               </ai-uploader> | ||||
|               <ai-audio :src="formData.file[0].url" style="width: 40px;height: 40px;margin-top:20px;" v-if="formData.file.length"></ai-audio> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </el-form> | ||||
|       </template> | ||||
|       <template #footer> | ||||
|         <el-button @click="cancel">取消</el-button> | ||||
|         <el-button type="primary" @click="confirm()">提交</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'Add', | ||||
|   components: {}, | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     instance: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       formData: { | ||||
|         type: '1', | ||||
|         name: '', | ||||
|         content: '', | ||||
|         file: [], | ||||
|         url: '' | ||||
|       }, | ||||
|       formRules: { | ||||
|         name: [ | ||||
|           { required: true, message: '请输入媒资名称', trigger: 'change' } | ||||
|         ], | ||||
|         content: [ | ||||
|           { required: true, message: '请输入文本内容', trigger: 'change' } | ||||
|         ], | ||||
|         file: [ | ||||
|           { required: true, message: '请上传音频', trigger: 'change' } | ||||
|         ], | ||||
|       }, | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|   }, | ||||
|   created() { | ||||
|     this.instance.defaults.timeout = 6000000 | ||||
|   }, | ||||
|   methods: { | ||||
|     confirm() { | ||||
|       this.$refs['ruleForm'].validate((valid) => { | ||||
|         if (valid) { | ||||
|           if(this.formData.file.length) { | ||||
|             this.formData.url = this.formData.file[0].url | ||||
|           } | ||||
|           this.instance.post(`/app/appdlbresource/addResource`,  {...this.formData}).then((res) => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('提交成功') | ||||
|               setTimeout(() => { | ||||
|                 this.cancel(true) | ||||
|               }, 1000) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 返回按钮 | ||||
|     cancel(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: !!isRefresh, | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .Add { | ||||
|   height: 100%; | ||||
|   .ai-detail__title { | ||||
|     background-color: #fff; | ||||
|   } | ||||
|   .ai-detail__content { | ||||
|     .ai-detail__content--wrapper { | ||||
|       .el-form { | ||||
|         background-color: #fff; | ||||
|         padding: 0 60px; | ||||
|         .flex { | ||||
|           display: flex; | ||||
|           flex-wrap: wrap; | ||||
|           justify-content: space-between; | ||||
|           .el-form-item { | ||||
|             width: 48%; | ||||
|           } | ||||
|           .buildingTypes { | ||||
|             width: 100%; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| ::v-deep .mapDialog { | ||||
|   .el-dialog__body { | ||||
|     padding: 0; | ||||
|  | ||||
|     .ai-dialog__content { | ||||
|       padding: 0; | ||||
|     } | ||||
|  | ||||
|     .ai-dialog__content--wrapper { | ||||
|       padding: 0 !important; | ||||
|       position: relative; | ||||
|     } | ||||
|  | ||||
|     #map { | ||||
|       width: 100%; | ||||
|       height: 420px; | ||||
|     } | ||||
|  | ||||
|     .searchPlaceInput { | ||||
|       position: absolute; | ||||
|       width: 250px; | ||||
|       top: 30px; | ||||
|       left: 25px; | ||||
|     } | ||||
|  | ||||
|     #searchPlaceOutput { | ||||
|       position: absolute; | ||||
|       width: 250px; | ||||
|       left: 25px; | ||||
|       height: initial; | ||||
|       top: 80px; | ||||
|       background: white; | ||||
|       z-index: 250; | ||||
|       max-height: 300px; | ||||
|       overflow-y: auto; | ||||
|  | ||||
|       .auto-item { | ||||
|         text-align: left; | ||||
|         font-size: 14px; | ||||
|         padding: 8px; | ||||
|         box-sizing: border-box; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										178
									
								
								packages/2.0.5/AppMediaManage/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								packages/2.0.5/AppMediaManage/components/List.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| <template> | ||||
|   <section class="AppPetitionManage"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="媒资管理" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar bottomBorder> | ||||
|           <template slot="left"> | ||||
|             <ai-select v-model="search.type" placeholder="媒资类型" clearable :selectList="$dict.getDict('dlbResourceType')" | ||||
|                        @change=";(page.current = 1), getList()"></ai-select> | ||||
|           </template> | ||||
|           <template slot="right"> | ||||
|             <el-input v-model="search.name" size="small" placeholder="媒资名称" clearable | ||||
|                       @keyup.enter.native=";(page.current = 1), getList()" | ||||
|                       @clear=";(page.current = 1), (search.name = ''), getList()" suffix-icon="iconfont iconSearch"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-search-bar class="ai-search-ba mar-t10"> | ||||
|           <template slot="left"> | ||||
|             <el-button icon="iconfont iconAdd" type="primary" size="small" @click="onAdd('')">添加</el-button> | ||||
|             <el-button icon="iconfont iconDelete" size="small" @click="removeAll" :disabled="ids.length == 0">删除 | ||||
|             </el-button> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" ref="aitableex" | ||||
|                   :current.sync="page.current" :size.sync="page.size" @getList="getList" | ||||
|                   @selection-change="(v) => (ids = v.map((e) => e.id))"> | ||||
|           <el-table-column slot="content" label="内容" width="200" show-overflow-tooltip> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <span type="text" v-if="row.type == 3">{{ row.content }}</span> | ||||
|               <ai-audio v-else-if="row.type == 1 && row.url" :src="row.url" skin="flat"/> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|           <el-table-column slot="options" label="操作" align="center" width="180" fixed="right"> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <el-button type="text" @click="remove(row.id)">删除</el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'List', | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     instance: Function, | ||||
|     params: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       isAdd: false, | ||||
|       page: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|       }, | ||||
|       total: 0, | ||||
|       search: { | ||||
|         type: '', | ||||
|         name: '', | ||||
|       }, | ||||
|       id: '', | ||||
|       ids: [], | ||||
|       colConfigs: [ | ||||
|         {type: 'selection', width: 100, align: 'center'}, | ||||
|         { | ||||
|           prop: 'name', | ||||
|           label: '媒资名称', | ||||
|         }, | ||||
|         { | ||||
|           prop: 'type', | ||||
|           label: '媒资类型', | ||||
|           width: '100', | ||||
|           align: 'center', | ||||
|           render: (h, {row}) => { | ||||
|             return h('span', null, this.dict.getLabel('dlbResourceType', row.type)) | ||||
|           }, | ||||
|         }, | ||||
|         { | ||||
|           slot: 'content', | ||||
|         }, | ||||
|         {prop: 'createTime', label: '创建时间', align: 'center'}, | ||||
|         { | ||||
|           prop: 'createUserName', | ||||
|           label: '创建人', | ||||
|           align: 'center', | ||||
|         }, | ||||
|         // { prop: 'liveBuildingArea', label: '状态', align: 'center',width: 120 }, | ||||
|         // { prop: 'liveBuildingArea', label: '发布次数', align: 'center',width: 120 }, | ||||
|         { | ||||
|           slot: 'options', | ||||
|           label: '操作', | ||||
|           align: 'center', | ||||
|         }, | ||||
|       ], | ||||
|       tableData: [], | ||||
|       areaId: '', | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     param() { | ||||
|       return { | ||||
|         ...this.search, | ||||
|         areaId: this.user.info?.areaId, | ||||
|         ids: this.ids, | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load('dlbResourceType').then(() => { | ||||
|       this.getList() | ||||
|     }) | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getList() { | ||||
|       this.instance | ||||
|       .post(`/app/appdlbresource/list`, null, { | ||||
|         params: { | ||||
|           ...this.page, | ||||
|           ...this.search, | ||||
|         }, | ||||
|       }) | ||||
|       .then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.tableData = res.data.records | ||||
|           this.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 添加 | ||||
|     onAdd(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'add', | ||||
|         params: { | ||||
|           id: id || '', | ||||
|           areaId: this.areaId, | ||||
|         }, | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     // 删除 | ||||
|     remove(id) { | ||||
|       this.$confirm('确定删除该数据?').then(() => { | ||||
|         this.instance.post(`/app/appdlbresource/delete?id=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('删除成功!') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     removeAll() { | ||||
|       var id = this.ids.join(',') | ||||
|       this.remove(id) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppPetitionManage { | ||||
|   height: 100%; | ||||
|  | ||||
|   .mar-t10 { | ||||
|     margin-top: 10px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										70
									
								
								packages/2.0.5/AppMonitoringObject/AppMonitoringObject.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								packages/2.0.5/AppMonitoringObject/AppMonitoringObject.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| <template> | ||||
|   <div class="AppMonitoringObject"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component | ||||
|         ref="component" | ||||
|         :is="component" | ||||
|         @change="onChange" | ||||
|         :params="params" | ||||
|         :instance="instance" | ||||
|         :dict="dict" | ||||
|       ></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from "./components/list"; | ||||
| import Add from "./components/add"; | ||||
| export default { | ||||
|   name: "AppMonitoringObject", | ||||
|   label: "监测对象", | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: "List", | ||||
|       params: {}, | ||||
|       include: [], | ||||
|     }; | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     List, Add  | ||||
|   }, | ||||
|  | ||||
|   mounted() {}, | ||||
|  | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === "Add") { | ||||
|         this.component = "Add"; | ||||
|         this.params = data.params; | ||||
|       } | ||||
|  | ||||
|       if (data.type === "List") { | ||||
|         this.component = "List"; | ||||
|         this.params = data.params; | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (data.isRefresh) { | ||||
|             this.$refs.component.getTableData(); | ||||
|           } | ||||
|         }); | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppMonitoringObject { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										797
									
								
								packages/2.0.5/AppMonitoringObject/components/add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										797
									
								
								packages/2.0.5/AppMonitoringObject/components/add.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,797 @@ | ||||
| <template> | ||||
|   <section style="height: 100%"> | ||||
|     <ai-detail class="add"> | ||||
|       <template #title> | ||||
|         <ai-title :title="params.id ? '监测对象详情' : '新增监测对象'" :isShowBack="true" :isShowBottomBorder="true" @onBackClick="cancel(false)"> | ||||
|           <template slot="rightBtn" v-if="params.id && navIndex != 1"> | ||||
|             <el-button size="small" icon="iconfont iconEdit" type="primary" v-if="!isEdit" @click="isEdit=true">编辑</el-button> | ||||
|             <el-button size="small" icon="iconfont" type="primary" v-if="isEdit" @click="save">保存</el-button> | ||||
|             <el-button size="small" icon="iconfont" v-if="isEdit" @click="getDetail(),isEdit=false">取消</el-button> | ||||
|           </template> | ||||
|         </ai-title> | ||||
|       </template> | ||||
|       <template #content> | ||||
|         <el-form ref="rules" :model="forms" :rules="formRules" size="small" label-suffix=":" label-width="136px">    | ||||
|           <div class="nav-list" v-if="params.id"> | ||||
|             <div class="nav-item" :class="navIndex != 1 ? 'active' : ''" @click="navIndex=0">基本信息</div> | ||||
|             <div class="nav-item" :class="navIndex == 1 ? 'active' : ''" @click="navIndex=1;getLogList()">帮扶日志</div> | ||||
|           </div> | ||||
|           <div v-if="navIndex != 1"> | ||||
|             <ai-card title="基础信息"> | ||||
|               <template slot="content"> | ||||
|                 <div v-if="isEdit"> | ||||
|                   <div class="above"> | ||||
|                     <div class="left"> | ||||
|                       <el-form-item label="监测对象类型" prop="type" > | ||||
|                         <ai-select v-model="forms.type" placeholder="请选择" clearable :selectList="$dict.getDict('fpType')"></ai-select> | ||||
|                       </el-form-item> | ||||
|                       <el-form-item label="联系方式" prop="phone" > | ||||
|                         <el-input v-model="forms.phone" placeholder="请输入" maxlength="20" show-word-limit></el-input> | ||||
|                       </el-form-item> | ||||
|                     </div> | ||||
|                     <div class="right"> | ||||
|                       <el-form-item label="是否搬迁" prop="move" > | ||||
|                         <ai-select v-model="forms.move" placeholder="请选择" clearable :selectList="$dict.getDict('fpYesOrNo')"></ai-select> | ||||
|                       </el-form-item> | ||||
|                     </div>              | ||||
|                   </div> | ||||
|                   <el-form-item label="所属区域" prop="addressAreaId"> | ||||
|                     <ai-area-select | ||||
|                       clearable | ||||
|                       always-show | ||||
|                       :instance="instance" | ||||
|                       v-model="forms.addressAreaId" | ||||
|                       @fullname="v=>forms.addressArea=v" | ||||
|                       :disabled-level="user.info.areaList.length" | ||||
|                     /> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="家庭住址" prop="address"> | ||||
|                     <el-input v-model="forms.address" placeholder="请输入" maxlength="50" show-word-limit></el-input> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="安置地区" prop="placeAreaId" v-if="forms.move == '01'"> | ||||
|                     <ai-area-select | ||||
|                       clearable | ||||
|                       always-show | ||||
|                       :instance="instance" | ||||
|                       v-model="forms.placeAreaId" | ||||
|                       @fullname="v=>forms.placeArea=v" | ||||
|                       :disabled-level="user.info.areaList.length" | ||||
|                     /> | ||||
|                   </el-form-item> | ||||
|                   <el-form-item label="安置详细地址" prop="place" v-if="forms.move == '01'"> | ||||
|                     <el-input v-model="forms.place" placeholder="请输入" maxlength="50" show-word-limit></el-input> | ||||
|                   </el-form-item> | ||||
|                 </div> | ||||
|                 <template v-else> | ||||
|                   <div class="above"> | ||||
|                     <div class="left"> | ||||
|                       <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                         <ai-info-item label="监测对象类型:"><span >{{dict.getLabel('fpType', forms.type)}}</span></ai-info-item> | ||||
|                         <ai-info-item label="联系方式:"><span >{{forms.phone}}</span></ai-info-item> | ||||
|                       </ai-wrapper> | ||||
|                     </div> | ||||
|                     <div class="right"> | ||||
|                       <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                         <ai-info-item label="是否搬迁:"><span >{{dict.getLabel('fpYesOrNo', forms.move)}}</span></ai-info-item> | ||||
|                       </ai-wrapper> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                   <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                     <ai-info-item label="所属区域:"><span >{{forms.addressArea}}</span></ai-info-item> | ||||
|                     <ai-info-item label="家庭住址:"><span >{{forms.address}}</span></ai-info-item> | ||||
|                     <ai-info-item label="安置地区:"  v-if="forms.move == '01'"><span >{{forms.placeArea}}</span></ai-info-item> | ||||
|                     <ai-info-item label="安置详细地址:"  v-if="forms.move == '01'"><span >{{forms.place}}</span></ai-info-item> | ||||
|                   </ai-wrapper> | ||||
|                 </template> | ||||
|               </template> | ||||
|             </ai-card> | ||||
|  | ||||
|             <ai-card title="家庭成员"> | ||||
|               <template slot="content"> | ||||
|                 <ai-search-bar v-if="isEdit"> | ||||
|                   <template #right><el-button type="primary" icon="iconfont iconAdd" @click="showAddFamily=true">添加</el-button></template> | ||||
|                 </ai-search-bar> | ||||
|                 <ai-table :tableData="forms.familyList" :colConfigs="colConfigs" :dict="dict" :isShowPagination="false"> | ||||
|                   <el-table-column slot="age" label="年龄" align="center" width="200"> | ||||
|                     <template v-slot="{ row }"> | ||||
|                       <span>{{getAge(row.idNumber)}}</span> | ||||
|                     </template> | ||||
|                   </el-table-column> | ||||
|                   <el-table-column slot="options" label="操作" align="center" fixed="right" width="200" v-if="isEdit"> | ||||
|                     <template v-slot="{ row, $index }"> | ||||
|                       <el-button type="text" @click="editFamily(row, $index)">编辑</el-button> | ||||
|                       <el-button type="text" @click="delFamily(row, $index)">删除</el-button> | ||||
|                     </template> | ||||
|                   </el-table-column> | ||||
|                 </ai-table> | ||||
|               </template> | ||||
|             </ai-card> | ||||
|  | ||||
|             <ai-card title="家庭情况"> | ||||
|               <template slot="content"> | ||||
|                 <div class="above" v-if="isEdit"> | ||||
|                   <div class="left"> | ||||
|                     <el-form-item label="是否危房" prop="dilapidatedHouse" > | ||||
|                       <ai-select v-model="forms.dilapidatedHouse" placeholder="请选择" clearable :selectList="$dict.getDict('fpYesOrNo')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="风险类型" prop="riskType" > | ||||
|                       <ai-select v-model="forms.riskType" placeholder="请选择" clearable :selectList="$dict.getDict('fpRiskType')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                   </div> | ||||
|                   <div class="right"> | ||||
|                     <el-form-item label="是否饮水安全" prop="waterSecurity" > | ||||
|                       <ai-select v-model="forms.waterSecurity" placeholder="请选择" clearable :selectList="$dict.getDict('fpYesOrNo')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                   </div>              | ||||
|                 </div> | ||||
|                 <div class="above" v-else> | ||||
|                   <div class="left"> | ||||
|                     <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                       <ai-info-item label="是否危房:"><span >{{dict.getLabel('fpYesOrNo', forms.dilapidatedHouse)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="风险类型:"><span >{{dict.getLabel('fpRiskType', forms.riskType)}}</span></ai-info-item> | ||||
|                     </ai-wrapper> | ||||
|                   </div> | ||||
|                   <div class="right"> | ||||
|                     <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                       <ai-info-item label="是否饮水安全:"><span >{{dict.getLabel('fpYesOrNo', forms.waterSecurity)}}</span></ai-info-item> | ||||
|                     </ai-wrapper> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </template> | ||||
|             </ai-card> | ||||
|  | ||||
|             <ai-card title="收入情况(单位:元)"> | ||||
|               <template slot="content"> | ||||
|                 <div v-if="isEdit"> | ||||
|                   <div class="above"> | ||||
|                     <div class="left"> | ||||
|                       <el-form-item label="工资收入"> | ||||
|                         <el-input v-model.number="forms.income1" placeholder="请输入" maxlength="10"></el-input> | ||||
|                       </el-form-item> | ||||
|                       <el-form-item label="财产性收入"> | ||||
|                         <el-input v-model.number="forms.income3" placeholder="请输入" maxlength="10"></el-input> | ||||
|                       </el-form-item> | ||||
|                       <el-form-item label="理赔收入"> | ||||
|                         <el-input v-model.number="forms.income8" placeholder="请输入" maxlength="10"></el-input> | ||||
|                       </el-form-item> | ||||
|                       <el-form-item label="合规自然支出"> | ||||
|                         <el-input v-model.number="forms.income9" placeholder="请输入" maxlength="10"></el-input> | ||||
|                       </el-form-item> | ||||
|                     </div> | ||||
|                     <div class="right"> | ||||
|                       <el-form-item label="生存经营收入"> | ||||
|                         <el-input v-model.number="forms.income2" placeholder="请输入" maxlength="10"></el-input> | ||||
|                       </el-form-item> | ||||
|                       <el-form-item label="转移性收入"> | ||||
|                         <el-input v-model.number="forms.income4" placeholder="请输入" maxlength="10"></el-input> | ||||
|                       </el-form-item> | ||||
|                       <el-form-item label="生产经营支出"> | ||||
|                         <el-input v-model.number="forms.income5" placeholder="请输入" maxlength="10"></el-input> | ||||
|                       </el-form-item> | ||||
|                     </div>           | ||||
|                   </div> | ||||
|                   <p style="font-size:14px;">备注:不填写时默认为0元</p>   | ||||
|                 </div> | ||||
|                 <div class="above" v-else> | ||||
|                   <div class="left"> | ||||
|                     <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                       <ai-info-item label="工资收入:"><span >{{forms.income1 || 0}}</span></ai-info-item> | ||||
|                       <ai-info-item label="财产性收入:"><span >{{forms.income3 || 0}}</span></ai-info-item> | ||||
|                       <ai-info-item label="理赔收入:"><span >{{forms.income8 || 0}}</span></ai-info-item> | ||||
|                       <ai-info-item label="合规自然支出:"><span >{{forms.income9 || 0}}</span></ai-info-item> | ||||
|                     </ai-wrapper> | ||||
|                   </div> | ||||
|                   <div class="right"> | ||||
|                     <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                       <ai-info-item label="生存经营收入:"><span >{{forms.income2 || 0}}</span></ai-info-item> | ||||
|                       <ai-info-item label="转移性收入:"><span >{{forms.income4 || 0}}</span></ai-info-item> | ||||
|                       <ai-info-item label="生产经营支出:"><span >{{forms.income5 || 0}}</span></ai-info-item> | ||||
|                     </ai-wrapper> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </template> | ||||
|             </ai-card> | ||||
|  | ||||
|             <ai-card title="帮扶情况"> | ||||
|               <template slot="content"> | ||||
|                 <div class="above" v-if="isEdit"> | ||||
|                   <div class="left"> | ||||
|                     <el-form-item label="产业帮扶" prop="industrialAssistance" > | ||||
|                       <ai-select v-model="forms.industrialAssistance" placeholder="请选择" clearable :selectList="$dict.getDict('fpIndustrialAssistance')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="就业帮扶" prop="employmentAssistance" > | ||||
|                       <ai-select v-model="forms.employmentAssistance" placeholder="请选择" clearable :selectList="$dict.getDict('fpEmploymentAssistance')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="金融帮扶" prop="financialAssistance" > | ||||
|                       <ai-select v-model="forms.financialAssistance" placeholder="请选择" clearable :selectList="$dict.getDict('fpFinancialAssistance')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="公益岗位帮扶" prop="publicWelfarePostAssistance" > | ||||
|                       <ai-select v-model="forms.publicWelfarePostAssistance" placeholder="请选择" clearable :selectList="$dict.getDict('fpPublicWelfarePostAssistance')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="风险消除时间" prop="riskEliminationDate" v-if="forms.isRisk == 1"> | ||||
|                       <el-date-picker | ||||
|                         v-model="forms.riskEliminationDate" | ||||
|                         type="date" | ||||
|                         value-format="yyyy-MM-dd" | ||||
|                         size="small" | ||||
|                         placeholder="选择日期"> | ||||
|                       </el-date-picker> | ||||
|                     </el-form-item> | ||||
|                   </div> | ||||
|                   <div class="right"> | ||||
|                      <el-form-item label="健康帮扶" prop="healthAssistance" > | ||||
|                       <ai-select v-model="forms.healthAssistance" placeholder="请选择" clearable :selectList="$dict.getDict('fpHealthAssistance')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="教育帮扶" prop="educationalAssistance" > | ||||
|                       <ai-select v-model="forms.educationalAssistance" placeholder="请选择" clearable :selectList="$dict.getDict('fpEducationalAssistance')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="社会帮扶" prop="socialAssistance" > | ||||
|                       <ai-select v-model="forms.socialAssistance" placeholder="请选择" clearable :selectList="$dict.getDict('fpSocialAssistance')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="是否风险消除"> | ||||
|                       <ai-select v-model="forms.isRisk" placeholder="请选择" clearable :selectList="$dict.getDict('fpYesOrNo')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item label="风险消除方式" prop="riskEliminationMethod"  v-if="forms.isRisk == 1"> | ||||
|                       <ai-select v-model="forms.riskEliminationMethod" placeholder="请选择" clearable :selectList="$dict.getDict('fpRiskEliminationMethod')"></ai-select> | ||||
|                     </el-form-item> | ||||
|                   </div>           | ||||
|                 </div> | ||||
|                 <div class="above" v-else> | ||||
|                   <div class="left"> | ||||
|                     <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                       <ai-info-item label="产业帮扶:"><span >{{dict.getLabel('fpIndustrialAssistance', forms.industrialAssistance)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="就业帮扶:"><span >{{dict.getLabel('fpEmploymentAssistance', forms.employmentAssistance)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="金融帮扶:"><span >{{dict.getLabel('fpFinancialAssistance', forms.financialAssistance)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="公益岗位帮扶:"><span >{{dict.getLabel('fpPublicWelfarePostAssistance', forms.publicWelfarePostAssistance)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="风险消除时间:" v-if="forms.isRisk == 1"><span >{{forms.riskEliminationDate}}</span></ai-info-item> | ||||
|                     </ai-wrapper> | ||||
|                   </div> | ||||
|                   <div class="right"> | ||||
|                     <ai-wrapper label-width="120px"  :columnsNumber="1"  style="margin-top: 16px;"> | ||||
|                       <ai-info-item label="健康帮扶:"><span >{{dict.getLabel('fpHealthAssistance', forms.healthAssistance)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="教育帮扶:"><span >{{dict.getLabel('fpEducationalAssistance', forms.educationalAssistance)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="社会帮扶:"><span >{{dict.getLabel('fpSocialAssistance', forms.socialAssistance)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="是否风险消除:"><span >{{dict.getLabel('fpYesOrNo', forms.isRisk)}}</span></ai-info-item> | ||||
|                       <ai-info-item label="风险消除方式:" v-if="forms.isRisk == 1"><span >{{dict.getLabel('fpRiskEliminationMethod', forms.riskEliminationMethod)}}</span></ai-info-item> | ||||
|                     </ai-wrapper> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </template> | ||||
|             </ai-card> | ||||
|           </div> | ||||
|           <ai-card title="帮扶日志" v-if="navIndex == 1"> | ||||
|             <template #right> | ||||
|               <span class="edit-text" @click="showAddLog=true">新增日志</span> | ||||
|             </template> | ||||
|             <template slot="content"> | ||||
|               <div class="log-list" v-if="logList.length"> | ||||
|                 <div class="log-item" v-for="(item, index) in logList" :key="index"> | ||||
|                   <img src="https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132" alt=""> | ||||
|                   <div class="content"> | ||||
|                     <div class="heade-info"> | ||||
|                       <h2>{{item.createUserName}}</h2> | ||||
|                       <p>{{item.createTime}}</p> | ||||
|                     </div> | ||||
|                     <p class="text">{{item.detail}}</p> | ||||
|                     <div class="img-list"> | ||||
|                       <ai-uploader :disabled="true"  :instance="instance"  v-model="item.file" :limit="9"></ai-uploader> | ||||
|                     </div> | ||||
|                     <div class="footer-btn"> | ||||
|                       <span class="edit-text" @click="editLog(item)">编辑</span> | ||||
|                       <span class="edit-text" @click="delLog(item)">删除</span> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <ai-empty v-else></ai-empty> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|         </el-form> | ||||
|         <ai-dialog title="新增帮扶日志" :visible.sync="showAddLog" :customFooter="true"  :destroyOnClose="true"  border  width="900px"> | ||||
|           <el-form ref="logrules" :model="logInfo" :rules="formRules" size="small" label-suffix=":" label-width="150px"> | ||||
|             <el-form-item label="帮扶内容" prop="detail"> | ||||
|               <el-input v-model="logInfo.detail" type="textarea" placeholder="请输入" maxlength="500" show-word-limit></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="图片(最多9张)" > | ||||
|               <ai-uploader | ||||
|                 :isShowTip="true" | ||||
|                 :instance="instance" | ||||
|                 v-model="logInfo.file" | ||||
|                 fileType="img" | ||||
|                 acceptType=".png,.jpg,.jpeg" | ||||
|                 :limit="9"> | ||||
|                 <template slot="tips">最多上传9张图片,单张图片最大10MB<br/>支持.png,.jpg,.jpeg格式</template> | ||||
|               </ai-uploader> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|           <div class="dialog-footer" slot="footer" > | ||||
|             <el-button size="medium" @click="showAddLog=false">取消</el-button> | ||||
|             <el-button type="primary" size="medium" @click="addLog()">确认</el-button> | ||||
|           </div> | ||||
|         </ai-dialog> | ||||
|         <ai-dialog title="新增家庭成员" :visible.sync="showAddFamily" :customFooter="true"  :destroyOnClose="true"  border  width="900px"> | ||||
|           <el-form ref="addrules" :model="familyInfo" :rules="formRules" size="small" label-suffix=":" label-width="150px"> | ||||
|             <div class="above"> | ||||
|               <div class="left"> | ||||
|                 <el-form-item label="与户主关系" prop="relationship" > | ||||
|                   <ai-select v-model="familyInfo.relationship" placeholder="请选择" clearable :selectList="$dict.getDict('fpRelationship')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="性别" prop="sex" > | ||||
|                   <ai-select v-model="familyInfo.sex" placeholder="请选择" clearable :selectList="$dict.getDict('sex')" disabled></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="政治面貌" prop="politicalOutlook" > | ||||
|                   <ai-select v-model="familyInfo.politicalOutlook" placeholder="请选择" clearable :selectList="$dict.getDict('fpPoliticalOutlook')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="在校情况" prop="studentsInSchool" > | ||||
|                   <ai-select v-model="familyInfo.studentsInSchool" placeholder="请选择" clearable :selectList="$dict.getDict('fpStudentsInSchool')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="劳动技能" prop="laborSkills" > | ||||
|                   <ai-select v-model="familyInfo.laborSkills" placeholder="请选择" clearable :selectList="$dict.getDict('fpLaborSkills')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="务工时间" prop="workingMonths" > | ||||
|                    <el-input v-model.number="familyInfo.workingMonths" placeholder="请输入(月数)" maxlength="30" show-word-limit></el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="是否参加大病医保" prop="sicknessInsurance" > | ||||
|                   <ai-select v-model="familyInfo.sicknessInsurance" placeholder="请选择" clearable :selectList="$dict.getDict('fpYesOrNo')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="享受最低生活保障" prop="subsistenceAllowance" > | ||||
|                   <ai-select v-model="familyInfo.subsistenceAllowance" placeholder="请选择" clearable :selectList="$dict.getDict('fpYesOrNo')"></ai-select> | ||||
|                 </el-form-item> | ||||
|               </div> | ||||
|               <div class="right"> | ||||
|                 <el-form-item label="姓名" prop="name" > | ||||
|                   <el-input v-model.number="familyInfo.name" placeholder="请输入" maxlength="11" show-word-limit></el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="身份证号" prop="idNumber" > | ||||
|                   <ai-id size="small" v-model="familyInfo.idNumber" @change="getSex(familyInfo.idNumber)"/> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="民族" prop="nation" > | ||||
|                   <ai-select v-model="familyInfo.nation" placeholder="请选择" clearable :selectList="$dict.getDict('fpNation')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="文化程度" prop="education" > | ||||
|                   <ai-select v-model="familyInfo.education" placeholder="请选择" clearable :selectList="$dict.getDict('fpEducation')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="健康状况" prop="health" > | ||||
|                   <ai-select v-model="familyInfo.health" placeholder="请选择" clearable :selectList="$dict.getDict('fpHealth')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="务工区域" prop="workArea" > | ||||
|                   <el-input v-model="familyInfo.workArea" placeholder="请输入" maxlength="30" show-word-limit></el-input> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="是否参加医保" prop="medicalInsurance" > | ||||
|                   <ai-select v-model="familyInfo.medicalInsurance" placeholder="请选择" clearable :selectList="$dict.getDict('fpYesOrNo')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="是否参加养老保险" prop="endowmentInsurance" > | ||||
|                   <ai-select v-model="familyInfo.endowmentInsurance" placeholder="请选择" clearable :selectList="$dict.getDict('fpYesOrNo')"></ai-select> | ||||
|                 </el-form-item> | ||||
|                 <el-form-item label="是否特困供养" prop="destitute" > | ||||
|                   <ai-select v-model="familyInfo.destitute" placeholder="请选择" clearable :selectList="$dict.getDict('fpYesOrNo')"></ai-select> | ||||
|                 </el-form-item> | ||||
|               </div> | ||||
|             </div> | ||||
|           </el-form> | ||||
|           <div class="dialog-footer" slot="footer" > | ||||
|             <el-button  size="medium" @click="showAddFamily=false">取消</el-button> | ||||
|             <el-button  type="primary" size="medium" @click="addFamily()">确认</el-button> | ||||
|           </div> | ||||
|         </ai-dialog> | ||||
|       </template> | ||||
|       <template #footer v-if="!params.id"> | ||||
|         <el-button @click="cancel(false)" class="delete-btn footer-btn" >取 消</el-button> | ||||
|         <el-button type="primary" @click="save()"  class="footer-btn">提 交</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
| export default { | ||||
|   name: "add", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|     params: Object, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       forms: { | ||||
|         type: '', | ||||
|         phone: '', | ||||
|         move: '', | ||||
|         addressAreaId: '', | ||||
|         address: '', | ||||
|         placeAreaId: '', | ||||
|         dilapidatedHouse: '', | ||||
|         riskType: '', | ||||
|         waterSecurity: '', | ||||
|         income1: '', | ||||
|         income2: '', | ||||
|         income3: '', | ||||
|         income4: '', | ||||
|         income5: '', | ||||
|         income8: '', | ||||
|         income9: '', | ||||
|         isRisk: '', | ||||
|         riskEliminationDate: '', | ||||
|         riskEliminationMethod: '', | ||||
|         industrialAssistance: '', | ||||
|         employmentAssistance: '', | ||||
|         financialAssistance: '', | ||||
|         publicWelfarePostAssistance: '', | ||||
|         healthAssistance: '', | ||||
|         educationalAssistance: '', | ||||
|         socialAssistance: '', | ||||
|         familyList: [] | ||||
|       }, | ||||
|       navIndex: 0, | ||||
|       showAddFamily: false, | ||||
|       isEdit: false, | ||||
|       familyInfo: { | ||||
|         relationship: '', | ||||
|         sex: '', | ||||
|         politicalOutlook: '', | ||||
|         studentsInSchool: '', | ||||
|         laborSkills: '', | ||||
|         workingMonths: '', | ||||
|         sicknessInsurance: '', | ||||
|         subsistenceAllowance: '', | ||||
|         name: '', | ||||
|         idNumber: '', | ||||
|         nation: '', | ||||
|         education: '', | ||||
|         health: '', | ||||
|         workArea: '', | ||||
|         medicalInsurance: '', | ||||
|         endowmentInsurance: '', | ||||
|         destitute: '', | ||||
|       }, | ||||
|       editFamilyIndex: '', | ||||
|       showAddLog: false, | ||||
|       logList: [], | ||||
|       logInfo: { | ||||
|         detail: '', | ||||
|         file: [], | ||||
|         picture: '' | ||||
|       } | ||||
|     }; | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load('fpType', 'fpYesOrNo', 'fpRiskType', 'fpRiskEliminationMethod', 'fpIndustrialAssistance', 'fpEmploymentAssistance', 'fpFinancialAssistance', | ||||
|     'fpPublicWelfarePostAssistance', 'fpHealthAssistance', 'fpEducationalAssistance', 'fpSocialAssistance', 'fpRelationship', 'sex', 'fpPoliticalOutlook',  | ||||
|     'fpStudentsInSchool', 'fpLaborSkills', 'fpNation', 'fpEducation', 'fpHealth') | ||||
|     if (this.params.id) { | ||||
|       this.getDetail() | ||||
|       this.isEdit = false | ||||
|     } else { | ||||
|       this.isEdit = true | ||||
|       this.forms.addressAreaId = this.user.info.areaId | ||||
|       this.forms.placeAreaId = this.user.info.areaId | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     formRules() { | ||||
|       return { | ||||
|         type: [{ required: true, message: "请选择监测对象类型", trigger: "change" }], | ||||
|         move: [{ required: true, message: "请选择是否搬迁", trigger: "change" }], | ||||
|         phone: [{ required: true, message: "请输入联系方式", trigger: "change" }], | ||||
|         addressAreaId: [ | ||||
|           {required: true, message: "请选择所属区域"}, | ||||
|           {trigger:'blur',validator: (r, v, cb) => /0{3}$/g.test(v) ? cb('请选择到村/社区') : cb()} | ||||
|         ], | ||||
|         address: [{ required: true, message: "请输入家庭住址", trigger: "change" }], | ||||
|         placeAreaId: [ | ||||
|           {required: true, message: "请选择安置地区"}, | ||||
|           {trigger:'blur',validator: (r, v, cb) => /0{3}$/g.test(v) ? cb('请选择到村/社区') : cb()} | ||||
|         ], | ||||
|         place: [{ required: true, message: "请输入安置详细住址", trigger: "change" }], | ||||
|         riskEliminationMethod: [{ required: true, message: "请选择风险消除方式", trigger: "change" }], | ||||
|         riskEliminationDate: [{ required: true, message: "请选择风险消除时间", trigger: "change" }], | ||||
|  | ||||
|         relationship: [{ required: true, message: "请选择与户主关系", trigger: "change" }], | ||||
|         name: [{ required: true, message: "请输入姓名", trigger: "change" }], | ||||
|         idNumber: [{ required: true, message: "请输入证件号码", trigger: "change" }], | ||||
|         studentsInSchool: [{ required: true, message: "请选择在校情况", trigger: "change" }], | ||||
|         health: [{ required: true, message: "请选择健康情况", trigger: "change" }],  | ||||
|         sicknessInsurance: [{ required: true, message: "请选择是否大病医保", trigger: "change" }], | ||||
|         subsistenceAllowance: [{ required: true, message: "请选择享受最低生活保障", trigger: "change" }], | ||||
|         medicalInsurance: [{ required: true, message: "请选择是否参加医保", trigger: "change" }], | ||||
|         endowmentInsurance: [{ required: true, message: "请选择是否参加养老保险", trigger: "change" }], | ||||
|         destitute: [{ required: true, message: "请选择是否特困供养", trigger: "change" }], | ||||
|         detail: [{ required: true, message: "请输入帮扶内容", trigger: "change" }], | ||||
|       }; | ||||
|     }, | ||||
|     ...mapState(['user']), | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {label: "与户主关系", prop: "relationship", dict: 'fpRelationship', align: 'center'}, | ||||
|         {label: "姓名", prop: "name", align: 'center'}, | ||||
|         {label: "性别", prop: "sex", dict: 'sex', align: 'center'}, | ||||
|         {slot: 'age'}, | ||||
|         { | ||||
|           label: "身份证号", width: "160px", align: 'center', | ||||
|           render: (h, {row}) => h('span', null, this.idCardNoUtil.hideId(row.idNumber)) | ||||
|         }, | ||||
|         {slot: "options"}, | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     save() { | ||||
|       this.$refs["rules"].validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.confirmSave() | ||||
|         } else { | ||||
|           return false; | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     confirmSave() { | ||||
|       var isHolder = false  //家庭成员必须有户主 | ||||
|       if(this.forms.familyList.length) { | ||||
|         this.forms.familyList.map((item) => { | ||||
|           if(item.relationship == '01') { | ||||
|             isHolder = true | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|       if(!isHolder) { | ||||
|         return this.$message.error('家庭成员必须添加户主信息'); | ||||
|       } | ||||
|       if(this.forms.isRisk == '01') { | ||||
|         this.forms.status = 1 | ||||
|       } | ||||
|       this.instance .post( `/app/apppreventionreturntopoverty/addOrUpdate`, { ...this.forms}).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           if (!this.params.id) { | ||||
|             this.cancel(true) | ||||
|           } else { | ||||
|             this.isEdit = false | ||||
|             this.getDetail() | ||||
|           } | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     getDetail() { | ||||
|       this.instance.post(`/app/apppreventionreturntopoverty/queryDetailById?id=${this.params.id}`).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.forms = { ...this.forms, ...res.data } | ||||
|           if(this.forms.riskEliminationDate) { | ||||
|             this.forms.isRisk = '01' | ||||
|           }else { | ||||
|             this.forms.isRisk = '02' | ||||
|           } | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     addFamily() { | ||||
|       this.$refs["addrules"].validate((valid) => { | ||||
|         if (valid) { | ||||
|           if(this.editFamilyIndex === '') { | ||||
|             this.forms.familyList.push(this.familyInfo) | ||||
|           }else { | ||||
|             this.$set(this.forms.familyList, this.editFamilyIndex, this.familyInfo) | ||||
|           } | ||||
|  | ||||
|           if(this.forms.isRisk == '02') { | ||||
|             this.forms.riskEliminationDate = '' | ||||
|             this.forms.riskEliminationMethod = '' | ||||
|           } | ||||
|            | ||||
|           this.showAddFamily = false | ||||
|           this.editFamilyIndex = '' | ||||
|           this.familyInfo = Object.assign({},this.$options.data().familyInfo); | ||||
|         } else { | ||||
|           return false; | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     editFamily(item, index) { | ||||
|       this.showAddFamily = true | ||||
|       this.editFamilyIndex = index | ||||
|       this.familyInfo = {...item} | ||||
|     }, | ||||
|     delFamily(item, index) { | ||||
|       this.$confirm("是否要删除该家庭成员", { | ||||
|         type: 'error' | ||||
|       }).then(() => { | ||||
|           this.$message({message: '家庭成员删除成功', type: 'success'}); | ||||
|           this.forms.familyList.splice(index, 1) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     getAge(UUserCard) { | ||||
|       const myDate = new Date(); | ||||
|       const month = myDate.getMonth() + 1; | ||||
|       const day = myDate.getDate(); | ||||
|       let age = myDate.getFullYear() - UUserCard.substring(6, 10) - 1; | ||||
|       if ( UUserCard.substring(10, 12) < month ||  (UUserCard.substring(10, 12) == month &&  UUserCard.substring(12, 14) <= day)) { | ||||
|         age++; | ||||
|       } | ||||
|       return age | ||||
|     }, | ||||
|     getSex(UUserCard) { | ||||
|       if (UUserCard) { | ||||
|         if (parseInt(UUserCard.substr(16, 1)) % 2 == 1) { | ||||
|           this.familyInfo.sex = '1' | ||||
|         } else { | ||||
|           this.familyInfo.sex = '0' | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     cancel (isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'List', | ||||
|         isRefresh: isRefresh ? true : false, | ||||
|       }) | ||||
|     }, | ||||
|     getLogList() { | ||||
|       this.instance.post(`/app/apppreventionreturntopovertylog/list?pid=${this.params.id}`).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           res.data.records.map((item) => { | ||||
|             item.file = JSON.parse(item.picture) | ||||
|           }) | ||||
|           this.logList = res.data.records | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     addLog() { | ||||
|       this.$refs["logrules"].validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.logInfo.picture = JSON.stringify(this.logInfo.file) | ||||
|           this.logInfo.pid = this.params.id | ||||
|           this.logInfo.createUserName = this.user.info.name | ||||
|           this.instance .post( `/app/apppreventionreturntopovertylog/addOrUpdate`, { ...this.logInfo}).then((res) => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message({message: this.logInfo.id ? '编辑帮扶日志成功' : '新增帮扶日志成功', type: 'success'}); | ||||
|               this.getLogList() | ||||
|               this.logInfo = Object.assign({},this.$options.data().logInfo) | ||||
|               this.showAddLog = false | ||||
|             } | ||||
|           }); | ||||
|         } else { | ||||
|           return false; | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     delLog(row) { | ||||
|       this.$confirm("是否要删除该帮扶日志", { | ||||
|         type: 'error' | ||||
|       }).then(() => { | ||||
|         this.instance.post(`/app/apppreventionreturntopovertylog/delete?ids=${row.id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message({message: '帮扶日志删除成功', type: 'success'}); | ||||
|             this.getLogList() | ||||
|           } | ||||
|         }); | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     editLog(row) { | ||||
|       this.logInfo = {...row} | ||||
|       this.logInfo.file = JSON.parse(row.picture) | ||||
|       this.showAddLog = true | ||||
|     } | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .add { | ||||
|   height: 100%; | ||||
|   .log-list{ | ||||
|     .log-item{ | ||||
|       display: flex; | ||||
|       border-bottom: 1px solid #ddd; | ||||
|       padding-top: 16px; | ||||
|       img{ | ||||
|         width: 48px; | ||||
|         height: 48px; | ||||
|         border-radius: 50%; | ||||
|         margin-right: 16px; | ||||
|       } | ||||
|       .content{ | ||||
|         width: calc(100% - 64px); | ||||
|         color: #000; | ||||
|         .heade-info{ | ||||
|           display: flex; | ||||
|           justify-content: space-between; | ||||
|           height: 36px; | ||||
|           line-height: 36px; | ||||
|           h2{ | ||||
|             font-size: 16px; | ||||
|             font-weight: 400; | ||||
|           } | ||||
|           p{ | ||||
|             font-size: 14px; | ||||
|             color: #333; | ||||
|           } | ||||
|         } | ||||
|         .text{ | ||||
|           font-size: 14px; | ||||
|           word-break: break-all; | ||||
|           margin-bottom: 8px; | ||||
|         } | ||||
|         .img-list{ | ||||
|           img{ | ||||
|             width: 150px; | ||||
|             height: 150px; | ||||
|             margin: 0 16px 16px 0; | ||||
|           } | ||||
|         } | ||||
|         .footer-btn{ | ||||
|           width: 100%; | ||||
|           text-align: right; | ||||
|           padding-bottom: 16px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     .log-item:nth-last-of-type(1) { | ||||
|       border-bottom: 0; | ||||
|     } | ||||
|   } | ||||
|   .ai-detail__title { | ||||
|     background-color: #fff; | ||||
|   } | ||||
|   .ai-detail__content { | ||||
|     .ai-detail__content--wrapper { | ||||
|       .el-form { | ||||
|         // background-color: #fff; | ||||
|         // padding: 0 60px; | ||||
|         .flex { | ||||
|           display: flex; | ||||
|           flex-wrap: wrap; | ||||
|           justify-content: space-between; | ||||
|           .el-form-item { | ||||
|             width: 48%; | ||||
|           } | ||||
|           .buildingTypes { | ||||
|             width: 100%; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   ::v-deep .el-tag { | ||||
|     margin-right: 8px; | ||||
|     color: #333333; | ||||
|   } | ||||
|   .footer-btn { | ||||
|     width: 92px; | ||||
|   } | ||||
|   .above{ | ||||
|     display: flex; | ||||
|     .left, .right{ | ||||
|       flex: 1; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .nav-list{ | ||||
|     position: absolute; | ||||
|     top: 100px; | ||||
|     left: -152px; | ||||
|     .nav-item{ | ||||
|       width: 120px; | ||||
|       height: 50px; | ||||
|       text-align: center; | ||||
|       line-height: 50px; | ||||
|       background-color: #fff; | ||||
|       cursor: pointer; | ||||
|       font-size: 16px; | ||||
|       color: #666; | ||||
|     } | ||||
|     .active{ | ||||
|       font-weight: 700; | ||||
|       color: #26f; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-date-editor.el-input, .el-date-editor.el-input__inner{ | ||||
|     width: 100%; | ||||
|   } | ||||
|   .edit-text{ | ||||
|     color:#2266FF; | ||||
|     margin-left: 16px; | ||||
|     cursor: pointer; | ||||
|     font-size: 12px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										272
									
								
								packages/2.0.5/AppMonitoringObject/components/list.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								packages/2.0.5/AppMonitoringObject/components/list.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,272 @@ | ||||
| <template> | ||||
|   <section class="list"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="监测对象" isShowBottomBorder isShowArea v-model="areaId" :instance="instance" @change="page.current=1,getTableData()"> | ||||
|         <template #rightBtn> | ||||
|           <el-button size="small" icon="iconfont iconSetting" type="primary" @click="showSet = true">预警规则</el-button> | ||||
|         </template> | ||||
|       </ai-title> | ||||
|       <template #blank> | ||||
|         <el-row type="flex"> | ||||
|           <div class="dataPane" v-for="(op,i) in dataPanes" :key="i"> | ||||
|             {{ [op.label, op.v].join(" ") }} | ||||
|           </div> | ||||
|         </el-row> | ||||
|         <div class="mainPane"> | ||||
|           <ai-search-bar> | ||||
|             <template #left> | ||||
|               <ai-select v-model="status" placeholder="请选择" clearable :selectList="$dict.getDict('fpStatus')" @change="page.current=1,getTableData()"></ai-select> | ||||
|             </template> | ||||
|             <template #right> | ||||
|               <el-input placeholder="姓名/身份证/户主联系方式"  v-model="search.name" size="small"  clearable @change="page.current=1,getTableData()" suffix-icon="iconfont iconSearch"/> | ||||
|             </template> | ||||
|           </ai-search-bar> | ||||
|           <ai-search-bar> | ||||
|             <template #left> | ||||
|               <el-button type="primary" icon="iconfont iconAdd" @click="toAdd('')">添加</el-button> | ||||
|               <el-button icon="iconfont iconDelete" :disabled="!ids.length" @click="handleDelete(ids)">删除</el-button> | ||||
|             </template> | ||||
|           </ai-search-bar> | ||||
|           <ai-table :tableData="tableData" :colConfigs="colConfigs" :total="page.total" :current.sync="page.current" | ||||
|             :size.sync="page.size" @getList="getTableData" :dict="dict" @selection-change="v=>ids=v.map(e=>e.id)"> | ||||
|             <el-table-column slot="options" label="操作" align="center" fixed="right" width="200"> | ||||
|               <template v-slot="{ row }"> | ||||
|                 <el-button type="text" @click="toAdd(row.id)">详情</el-button> | ||||
|                 <el-button type="text" @click="handleDelete(row.id)">删除</el-button> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column slot="options" label="状态" align="center" width="200"> | ||||
|               <template v-slot="{ row }"> | ||||
|                 <span :class="{'status1': row.status == 1, 'status0': row.status == 2}">{{dict.getLabel('fpStatus', row.status)}}</span> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </div> | ||||
|         <ai-dialog title="预警规则设置" :visible.sync="showSet" :customFooter="true"  :destroyOnClose="true"  border  width="900px"> | ||||
|           <el-form ref="rules" :model="setInfo" :rules="formRules" size="small" label-suffix=":" label-width="200px"> | ||||
|             <el-form-item label="家庭纯收入标准" prop="type0"> | ||||
|               <el-input v-model.number="setInfo.type0" placeholder="请输入" maxlength="8" show-word-limit></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="家庭人均纯收入标准" prop="type1"> | ||||
|               <el-input v-model.number="setInfo.type1" placeholder="请输入" maxlength="8" show-word-limit></el-input> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|           <div class="dialog-footer" slot="footer" > | ||||
|             <el-button size="medium" @click="showSet=false">取消</el-button> | ||||
|             <el-button type="primary" size="medium" @click="addSet()">确认</el-button> | ||||
|           </div> | ||||
|         </ai-dialog> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
|  | ||||
| export default { | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       areaId: "", | ||||
|       page: {current: 1, size: 10, total: 0}, | ||||
|       search: {inoculationType: "", name: ""}, | ||||
|       ids: [], | ||||
|       tableData: [], | ||||
|       staData: {}, | ||||
|       currIndex: 0, | ||||
|       options: [{ value: '0', label: '无风险'},{ value: '2', label: '未解除'}, { value: '1',  label: '已解除'}], | ||||
|       status: '', | ||||
|       showSet: false, | ||||
|       setInfo: { | ||||
|         type0: '', | ||||
|         type1: '' | ||||
|       }, | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     showDetail() { | ||||
|       return this.$route.hash == "#add" | ||||
|     }, | ||||
|     dataPanes() { | ||||
|       return [ | ||||
|         {label: "监测家庭户数", v: this.staData.jths || 0}, | ||||
|         {label: "监测对象总人数", v: this.staData.zrs || 0}, | ||||
|         {label: "解除风险人数", v: this.staData.fxxcrs || 0}, | ||||
|         {label: "风险解除率", v: this.staData.jcl || 0}, | ||||
|       ] | ||||
|     }, | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {type: "selection", align: 'center'}, | ||||
|         {label: "户主姓名", prop: "name", align: 'center'}, | ||||
|         {label: "性别", prop: "sex", dict: 'sex', align: 'center'}, | ||||
|         { | ||||
|           label: "身份证号", width: "160px", align: 'center', | ||||
|           render: (h, {row}) => h('span', null, this.idCardNoUtil.hideId(row.idNumber)) | ||||
|         }, | ||||
|         {label: "户主联系方式", prop: "phone", align: 'center'}, | ||||
|         { | ||||
|           label: "家庭住址", width: "160px", align: 'center', | ||||
|           render: (h, {row}) => h('span', null, row.addressArea+row.address) | ||||
|         }, | ||||
|         {label: "风险类型", prop: "riskType", dict: 'fpRiskType', align: 'center'}, | ||||
|         {label: "最后更新时间", prop: "createTime", align: 'center'}, | ||||
|         {slot: "status"}, | ||||
|         {label: "操作人", prop: "createUserName", align: 'center'}, | ||||
|         {slot: "options"}, | ||||
|       ] | ||||
|     }, | ||||
|     formRules() { | ||||
|       return { | ||||
|         type0: [{ required: true, message: "请输入家庭纯收入标准", trigger: "change" }], | ||||
|         type1: [{ required: true, message: "请输入家庭人均纯收入标准", trigger: "change" }], | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.areaId = JSON.parse(JSON.stringify(this.user.info.areaId)) | ||||
|     this.dict.load('sex', 'fpRiskType', 'fpStatus').then(() => { | ||||
|       this.getTableData() | ||||
|       this.getSetInfo() | ||||
|     }) | ||||
|   }, | ||||
|   methods: { | ||||
|     getNum() { | ||||
|       this.instance.post(`/app/apppreventionreturntopoverty/statistics-list`).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.staData = res.data | ||||
|           this.staData.jcl = (this.staData.fxxcrs / this.staData.jths).toFixed(2) * 100 + '%' | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     toAdd(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'Add', | ||||
|         params: { | ||||
|           id: id || '' | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getStaData() { | ||||
|       this.instance.post(`/app/appvaccineinoculationuser/countByAreaId`, null, { | ||||
|         params: {areaId: this.areaId} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.staData = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     addSet() { | ||||
|       this.$refs["rules"].validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.instance.post(`/app/apppreventionreturntopovertyalarmconfig/addOrUpdate`, this.setInfo).then((res) => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message({message: '预警规则设置成功', type: 'success'}); | ||||
|               this.getSetInfo() | ||||
|               this.showSet = false | ||||
|             } | ||||
|           }); | ||||
|         } else { | ||||
|           return false; | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     getSetInfo() { | ||||
|       this.instance.post(`/app/apppreventionreturntopovertyalarmconfig/query`).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.setInfo = {...res.data} | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     getTableData() { | ||||
|       this.page.current == 1 && this.getStaData() | ||||
|       this.instance.post(`/app/apppreventionreturntopoverty/list`, null, { | ||||
|         params: {...this.search, ...this.page, addressAreaId: this.areaId, status: this.status} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data.records | ||||
|           this.page.total = res.data.total | ||||
|           this.tableData.map((item) => { | ||||
|             item.createTime = item.createTime.substring(0, 10) | ||||
|           }) | ||||
|           this.getNum() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleDelete(ids) { | ||||
|       ids = ids?.toString() | ||||
|       this.$confirm("确定要删除该条数据吗?").then(() => { | ||||
|         this.instance.post(`/app/apppreventionreturntopoverty/delete`, null, { | ||||
|           params: {ids} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("删除成功!"); | ||||
|             this.getTableData(); | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     resetSearch() { | ||||
|       this.page.current = 1 | ||||
|       this.search = {} | ||||
|       this.getTableData() | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .list { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .dataPane { | ||||
|     flex: 1; | ||||
|     min-width: 0; | ||||
|     background: #FFFFFF; | ||||
|     box-shadow: 0 4px 6px -2px rgba(15, 15, 21, 0.15); | ||||
|     border-radius: 2px; | ||||
|     margin-bottom: 16px; | ||||
|     margin-right: 16px; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     height: 60px; | ||||
|  | ||||
|     &:last-of-type { | ||||
|       margin-right: 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .mainPane { | ||||
|     background: #fff; | ||||
|     padding: 12px 16px; | ||||
|     .ai-table__header { | ||||
|       padding: 2px 0; | ||||
|     } | ||||
|   } | ||||
|   .tab-text{ | ||||
|     display: inline-block; | ||||
|     font-size: 14px; | ||||
|     width: 150px; | ||||
|     height: 32px; | ||||
|     line-height: 32px; | ||||
|     color: #333; | ||||
|     cursor: pointer; | ||||
|   } | ||||
|   .active-tab{ | ||||
|     color: #26f; | ||||
|   } | ||||
|   .status0{ | ||||
|     color: rgb(255, 136, 34); | ||||
|   } | ||||
|   .status1{ | ||||
|     color: rgb(46, 162, 34); | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										204
									
								
								packages/2.0.5/AppVaccination/AppVaccination.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								packages/2.0.5/AppVaccination/AppVaccination.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,204 @@ | ||||
| <template> | ||||
|   <section class="AppVaccination"> | ||||
|     <ai-list v-if="!showDetail"> | ||||
|       <ai-title slot="title" title="疫苗接种" isShowBottomBorder isShowArea v-model="areaId" :instance="instance" | ||||
|                 @change="page.current=1,getTableData()"/> | ||||
|       <template #blank> | ||||
|         <el-row type="flex"> | ||||
|           <div class="dataPane" v-for="(op,i) in dataPanes" :key="i"> | ||||
|             {{ [op.label, op.v].join(" ") }} | ||||
|           </div> | ||||
|         </el-row> | ||||
|         <div class="mainPane"> | ||||
|           <ai-search-bar> | ||||
|             <template #left> | ||||
|               <ai-select placeholder="接种状况" v-model="search.inoculationType" @change="page.current=1,getTableData()" | ||||
|                          :selectList="dict.getDict('vaccineInoculationType')"/> | ||||
|             </template> | ||||
|             <template #right> | ||||
|               <el-input placeholder="姓名/身份证/联系方式" | ||||
|                         v-model="search.name" | ||||
|                         size="small" | ||||
|                         clearable | ||||
|                         @change="page.current=1,getTableData()" | ||||
|                         suffix-icon="iconfont iconSearch"/> | ||||
|             </template> | ||||
|           </ai-search-bar> | ||||
|           <ai-search-bar> | ||||
|             <template #left> | ||||
|               <el-button type="primary" icon="iconfont iconAdd" @click="$router.push({hash:'#add'})">添加</el-button> | ||||
|               <el-button icon="iconfont iconDelete" :disabled="!ids.length" @click="handleDelete(ids)">删除</el-button> | ||||
|             </template> | ||||
|             <template #right> | ||||
|               <ai-import :instance="instance" :dict="dict" name="疫苗接种" suffixName="xlsx" | ||||
|                          type="appvaccineinoculationuser" @onSuccess="resetSearch"/> | ||||
|               <ai-download url="/app/appvaccineinoculationuser/export" :params="{...search,areaId,ids:ids.toString()}" | ||||
|                            :instance="instance" fileName="疫苗接种导出文件"/> | ||||
|             </template> | ||||
|           </ai-search-bar> | ||||
|           <ai-table :tableData="tableData" :colConfigs="colConfigs" :total="page.total" :current.sync="page.current" | ||||
|                     :size.sync="page.size" @getList="getTableData" :dict="dict" | ||||
|                     @selection-change="v=>ids=v.map(e=>e.id)"> | ||||
|             <el-table-column slot="vaccinationDate" label="接种日期" align="center" class-name="vaccinationDate"> | ||||
|               <el-table-column label="第一次" align="center" prop="firstDate"/> | ||||
|               <el-table-column label="第二次" align="center" prop="secondDate"/> | ||||
|               <el-table-column label="第三次" align="center" prop="thirdDate"/> | ||||
|             </el-table-column> | ||||
|             <el-table-column slot="options" label="操作" align="center" fixed="right"> | ||||
|               <template slot-scope="{row:{id}}"> | ||||
|                 <el-button type="text" @click="$router.push({hash:'#add',query:{id}})">编辑</el-button> | ||||
|                 <el-button type="text" @click="handleDelete(id)">删除</el-button> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </div> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <add-vaccination v-else :dict="dict" :instance="instance"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
| import AddVaccination from "./addVaccination"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppVaccination", | ||||
|   components: {AddVaccination}, | ||||
|   label: "疫苗接种", | ||||
|   provide() { | ||||
|     return { | ||||
|       top: this | ||||
|     } | ||||
|   }, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       areaId: "", | ||||
|       page: {current: 1, size: 10, total: 0}, | ||||
|       search: {inoculationType: "", name: ""}, | ||||
|       ids: [], | ||||
|       tableData: [], | ||||
|       staData: {} | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     showDetail() { | ||||
|       return this.$route.hash == "#add" | ||||
|     }, | ||||
|     dataPanes() { | ||||
|       return [ | ||||
|         {label: "总接种人数", v: this.staData.zjzrs || 0}, | ||||
|         {label: "已接种第一针人数", v: this.staData.yjzdyzrs || 0}, | ||||
|         {label: "已接种第二针人数", v: this.staData.yjzdezrs || 0}, | ||||
|         {label: "已接种第三针人数", v: this.staData.yjzdszrs || 0}, | ||||
|       ] | ||||
|     }, | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {type: "selection", align: 'center'}, | ||||
|         {label: "姓名", prop: "name", align: 'center'}, | ||||
|         {label: "性别", prop: "sex", dict: 'sex', align: 'center'}, | ||||
|         {label: "出生日期", prop: "birthday", align: 'center'}, | ||||
|         { | ||||
|           label: "身份证号", width: "160px", align: 'center', | ||||
|           render: (h, {row}) => h('span', null, this.idCardNoUtil.hideId(row.idNumber)) | ||||
|         }, | ||||
|         {label: "所属地区", prop: "areaName", align: 'center'}, | ||||
|         {label: "住址", prop: "address", width: "200px", align: 'center'}, | ||||
|         {label: "联系方式", prop: "phone", align: 'center'}, | ||||
|         {slot: 'vaccinationDate'}, | ||||
|         {slot: "options"}, | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.areaId = JSON.parse(JSON.stringify(this.user.info.areaId)) | ||||
|     this.dict.load('sex', 'vaccineInoculationType') | ||||
|     this.getTableData() | ||||
|   }, | ||||
|   methods: { | ||||
|     getStaData() { | ||||
|       this.instance.post(`/app/appvaccineinoculationuser/countByAreaId`, null, { | ||||
|         params: {areaId: this.areaId} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.staData = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getTableData() { | ||||
|       this.page.current == 1 && this.getStaData() | ||||
|       this.instance.post(`/app/appvaccineinoculationuser/list`, null, { | ||||
|         params: {...this.search, ...this.page, areaId: this.areaId} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data.records | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleDelete(ids) { | ||||
|       ids = ids?.toString() | ||||
|       this.$confirm("确定要删除该条数据吗?").then(() => { | ||||
|         this.instance.post(`/app/appvaccineinoculationuser/delete`, null, { | ||||
|           params: {ids} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("删除成功!"); | ||||
|             this.getTableData(); | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     resetSearch() { | ||||
|       this.page.current = 1 | ||||
|       this.search = {} | ||||
|       this.getTableData() | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppVaccination { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .dataPane { | ||||
|     flex: 1; | ||||
|     min-width: 0; | ||||
|     background: #FFFFFF; | ||||
|     box-shadow: 0 4px 6px -2px rgba(15, 15, 21, 0.15); | ||||
|     border-radius: 2px; | ||||
|     margin-bottom: 16px; | ||||
|     margin-right: 16px; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     height: 60px; | ||||
|  | ||||
|     &:last-of-type { | ||||
|       margin-right: 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .mainPane { | ||||
|     background: #fff; | ||||
|     padding: 12px 16px; | ||||
|     box-shadow: 0 4px 6px -2px rgba(15, 15, 21, 0.15); | ||||
|  | ||||
|     .vaccinationDate { | ||||
|       border-bottom: 1px solid #D0D4DC; | ||||
|     } | ||||
|  | ||||
|     .ai-table__header { | ||||
|       padding: 2px 0; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										235
									
								
								packages/2.0.5/AppVaccination/addVaccination.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								packages/2.0.5/AppVaccination/addVaccination.vue
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,235 @@ | ||||
| <template> | ||||
|   <section class="addVaccination"> | ||||
|     <ai-detail> | ||||
|       <ai-title slot="title" :title="addTitle" isShowBottomBorder | ||||
|                 isShowBack @onBackClick="back"/> | ||||
|       <template #content> | ||||
|         <el-form size="small" :model="form" ref="vaccinationForm" :rules="rules" label-width="100px"> | ||||
|           <ai-card title="基本信息"> | ||||
|             <template #content> | ||||
|               <el-form-item label="受种人姓名" prop="name"> | ||||
|                 <el-row type="flex" align="middle"> | ||||
|                   <el-input placeholder="请输入" v-model="form.name" :disabled="isEdit" clearable | ||||
|                             style="margin-right: 8px"/> | ||||
|                   <ai-person-select v-if="!isEdit" :instance="instance" @selectPerson="handleSelectPerson"/> | ||||
|                 </el-row> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="身份证号码" prop="idNumber"> | ||||
|                 <ai-id v-model="form.idNumber" @change="getInfoByIdNumber" :disabled="isEdit"/> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="性别" prop="sex"> | ||||
|                 <ai-select disabled v-model="form.sex" :selectList="dict.getDict('sex')"/> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="出生日期" prop="birthday"> | ||||
|                 <el-date-picker v-model="form.birthday" type="date" disabled/> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="联系方式" prop="phone"> | ||||
|                 <el-input v-model="form.phone" placeholder="请输入"/> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="所属地区" isLine prop="areaId"> | ||||
|                 <ai-area-select :instance="instance" v-model="form.areaId" always-show @name="v=>form.areaName=v"/> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="住址" isLine prop="address"> | ||||
|                 <el-input v-model="form.address" placeholder="请输入"/> | ||||
|               </el-form-item> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card title="接种情况"> | ||||
|             <template #right> | ||||
|               <el-button icon="iconfont iconAdd" type="text" @click="dialog=true">添加</el-button> | ||||
|             </template> | ||||
|             <template #content> | ||||
|               <el-form-item isLine label-width="0"> | ||||
|                 <ai-table :tableData="form.detailList" :colConfigs="colConfigs" :isShowPagination="false" :dict="dict"> | ||||
|                   <el-table-column slot="options" label="操作" align="center" fixed="right"> | ||||
|                     <template v-slot="{row,$index}"> | ||||
|                       <el-button type="text" @click="handleEdit(row,$index)">编辑</el-button> | ||||
|                       <el-button type="text" @click="handleDelete($index)">删除</el-button> | ||||
|                     </template> | ||||
|                   </el-table-column> | ||||
|                 </ai-table> | ||||
|               </el-form-item> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|         </el-form> | ||||
|       </template> | ||||
|       <template #footer> | ||||
|         <el-button @click="back">取消</el-button> | ||||
|         <el-button type="primary" @click="handleSubmit">提交</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|     <ai-dialog :visible.sync="dialog" title="接种情况" @closed="dialogForm={}" @onConfirm="handleConfirm"> | ||||
|       <el-form ref="appvaccineinoculationuser" size="small" :model="dialogForm" label-width="100px" :rules="rules"> | ||||
|         <el-form-item label="接种次数" prop="type"> | ||||
|           <ai-select v-model="dialogForm.type" :selectList="dict.getDict('vaccineType')"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="接种日期" prop="vaccinateDate"> | ||||
|           <el-date-picker v-model="dialogForm.vaccinateDate" value-format="yyyy-MM-dd"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="接种人员" prop="vaccinatePerson"> | ||||
|           <el-input v-model="dialogForm.vaccinatePerson"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="生产企业" prop="createCompany"> | ||||
|           <el-input v-model="dialogForm.createCompany"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="接种单位" prop="vaccinateUnit"> | ||||
|           <el-input v-model="dialogForm.vaccinateUnit"/> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
|  | ||||
| export default { | ||||
|   name: "addVaccination", | ||||
|   inject: ['top'], | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       form: {detailList: []}, | ||||
|       dialog: false, | ||||
|       dialogForm: {} | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     isEdit() { | ||||
|       return !!this.$route.query.id | ||||
|     }, | ||||
|     addTitle() { | ||||
|       return this.isEdit ? '编辑疫苗接种人员' : '新增疫苗接种人员' | ||||
|     }, | ||||
|     rules() { | ||||
|       return { | ||||
|         vaccinateDate: {required: true, message: "请选择 接种日期"}, | ||||
|         type: {required: true, message: "请选择 接种次数",}, | ||||
|         areaId: [ | ||||
|           {required: true, message: "请选择 所属地区"}, | ||||
|           {trigger:'blur',validator: (r, v, cb) => /0{3}$/g.test(v) ? cb('请选择到村/社区') : cb()} | ||||
|         ], | ||||
|         name: {required: true, message: "请填写 受种人姓名"}, | ||||
|         idNumber: {required: true, message: "请填写 身份号码"}, | ||||
|         sex: {required: true, message: "请填写 性别"}, | ||||
|         birthday: {required: true, message: "请填写 出生日期"}, | ||||
|         phone: {required: true, message: "请填写 联系方式"}, | ||||
|       } | ||||
|     }, | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {label: "类型", align: 'center', prop: "type", dict: 'vaccineType'}, | ||||
|         {label: "接种日期", align: 'center', prop: "vaccinateDate"}, | ||||
|         {label: "接种人员", align: 'center', prop: "vaccinatePerson"}, | ||||
|         {label: "生产企业", align: 'center', prop: "createCompany"}, | ||||
|         {label: "接种单位", align: 'center', prop: "vaccinateUnit"}, | ||||
|         {slot: "options"} | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     back() { | ||||
|       this.$router.push({}) | ||||
|     }, | ||||
|     getDetail() { | ||||
|       let {id} = this.$route.query | ||||
|       if (id) { | ||||
|         this.instance.post("/app/appvaccineinoculationuser/queryDetailById", null, { | ||||
|           params: {id} | ||||
|         }).then(res => { | ||||
|           if (res?.data) { | ||||
|             this.form = res.data | ||||
|           } | ||||
|         }) | ||||
|       } else { | ||||
|         this.$set(this.form,'areaId',JSON.parse(JSON.stringify(this.top.areaId))) | ||||
|       } | ||||
|     }, | ||||
|     handleSubmit() { | ||||
|       this.$refs.vaccinationForm?.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post("/app/appvaccineinoculationuser/addOrUpdate", this.form).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success("提交成功!") | ||||
|               this.top.resetSearch() | ||||
|               this.back() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleEdit(row, index) { | ||||
|       this.dialogForm = JSON.parse(JSON.stringify({...row, index})) | ||||
|       this.dialog = true | ||||
|     }, | ||||
|     handleConfirm() { | ||||
|       this.$refs.appvaccineinoculationuser.validate(v => { | ||||
|         if (v) { | ||||
|           if (this.dialogForm.index > -1) { | ||||
|             this.form.detailList.splice(this.dialogForm.index, 1, this.dialogForm) | ||||
|           } else { | ||||
|             this.form.detailList.push(this.dialogForm) | ||||
|           } | ||||
|           this.dialog = false | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleSelectPerson(v) { | ||||
|       let {name, idNumber, phone, currentAreaId:areaId, currentAddress:address} = v | ||||
|       this.form = {...this.form, name, idNumber, phone, areaId, address} | ||||
|     }, | ||||
|     getInfoByIdNumber(code) { | ||||
|       if (this.idCardNoUtil.checkIdCardNo(code)) { | ||||
|         let info = this.idCardNoUtil.getIdCardInfo(code) | ||||
|         this.form.sex = this.dict.getValue('sex', info.gender) | ||||
|         this.form.birthday = info.birthday | ||||
|         this.$forceUpdate() | ||||
|       } | ||||
|     }, | ||||
|     handleDelete(index) { | ||||
|       this.$confirm("是否要删除该条数据?").then(() => this.form.detailList.splice(index, 1)).catch(() => 0) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load('vaccineType') | ||||
|     this.getDetail() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .addVaccination { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .ai-card__body, .el-form { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|   } | ||||
|  | ||||
|   .ai-card { | ||||
|     width: 100%; | ||||
|   } | ||||
|  | ||||
|   .el-form-item { | ||||
|     width: 50%; | ||||
|  | ||||
|     &[isLine] { | ||||
|       width: 100%; | ||||
|     } | ||||
|  | ||||
|     .el-date-editor { | ||||
|       width: 100%; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-button { | ||||
|     .iconfont { | ||||
|       color: inherit | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										97
									
								
								packages/bigscreen/designer/AppDesigner.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								packages/bigscreen/designer/AppDesigner.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| <template> | ||||
|   <ai-list v-if="!isShowDetail"> | ||||
|     <template slot="title"> | ||||
|       <ai-title title="大屏列表" :isShowBottomBorder="false" :instance="instance"></ai-title> | ||||
|     </template> | ||||
|     <template slot="tabs"> | ||||
|       <el-tabs v-model="currIndex"> | ||||
|         <el-tab-pane v-for="(tab,i) in tabs" :key="i" :label="tab.label"> | ||||
|           <component :urlPrefix="urlPrefix" :areaId="areaId" :ref="tab.name" v-if="currIndex == i" :is="tab.comp" @change="onChange" lazy | ||||
|                      :instance="instance" :dict="dict" :permissions="permissions"/> | ||||
|         </el-tab-pane> | ||||
|       </el-tabs> | ||||
|     </template> | ||||
|   </ai-list> | ||||
|   <Add v-else-if="componentName === 'Add'" :urlPrefix="urlPrefix" :areaId="areaId" :params="params" :instance="instance" :dict="dict" | ||||
|        :permissions="permissions" @change="onChange"></Add> | ||||
|   <SourceData v-else-if="componentName === 'SourceData'" :urlPrefix="urlPrefix" :params="params" :instance="instance" :dict="dict" | ||||
|               :permissions="permissions" @change="onChange"></SourceData> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from './components/List.vue' | ||||
| import Add from './components/Add' | ||||
| import SourceData from './components/SourceData' | ||||
|  | ||||
| export default { | ||||
|   name: 'AppDesigner', | ||||
|   label: '大屏设计', | ||||
|  | ||||
|   components: { | ||||
|     List, | ||||
|     Add, | ||||
|     SourceData | ||||
|   }, | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|     urlPrefix: { | ||||
|       type: String, | ||||
|       default: '/app' | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     tabs() { | ||||
|       return [ | ||||
|         {label: '大屏列表', name: 'FormList', comp: List, permission: ''} | ||||
|       ].filter(() => { | ||||
|         return true | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       currIndex: '0', | ||||
|       componentName: '', | ||||
|       params: {}, | ||||
|       areaId: '', | ||||
|       isShowDetail: false | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       if (data.type === 'list') { | ||||
|         this.componentName = 'List' | ||||
|         this.isShowDetail = false | ||||
|         this.params = data.params | ||||
|  | ||||
|         if (data.isQuote) { | ||||
|           this.currIndex = 0 | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (data.type === 'add') { | ||||
|         this.componentName = 'Add' | ||||
|         this.isShowDetail = true | ||||
|         this.params = data.params | ||||
|       } | ||||
|  | ||||
|       if (data.type === 'SourceData') { | ||||
|         this.componentName = 'SourceData' | ||||
|         this.isShowDetail = true | ||||
|         this.params = data.params | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| </style> | ||||
							
								
								
									
										285
									
								
								packages/bigscreen/designer/components/Add.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								packages/bigscreen/designer/components/Add.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,285 @@ | ||||
| <template> | ||||
|   <ai-detail> | ||||
|     <template slot="title"> | ||||
|       <ai-title :title="id ? '编辑项目' : '添加项目'" isShowBack isShowBottomBorder @onBackClick="cancel(false)"> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|         <ai-card title="基本信息"> | ||||
|           <template #content> | ||||
|             <div class="ai-form"> | ||||
|               <el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入大屏项目名称', trigger: 'blur' }]"> | ||||
|                 <el-input size="small" :maxlength="30" placeholder="请输入大屏项目名称" v-model="form.name"></el-input> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="描述" style="width: 100%;" prop="description"> | ||||
|                 <el-input size="small" :maxlength="200" :rows="5" type="textarea" style="width: 100%;" | ||||
|                           placeholder="请输入描述" v-model="form.description"></el-input> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="是否开启" style="width: 100%;" prop="status"> | ||||
|                 <el-switch | ||||
|                     v-model="form.status" | ||||
|                     active-value="1" | ||||
|                     inactive-value="0"> | ||||
|                 </el-switch> | ||||
|               </el-form-item> | ||||
|             </div> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <ai-card title="大屏"> | ||||
|           <template #right> | ||||
|             <el-button @click="add('')" type="primary">添加大屏</el-button> | ||||
|             <el-button @click="dialog=true" type="primary">定制大屏</el-button> | ||||
|           </template> | ||||
|           <template #content> | ||||
|             <ai-table | ||||
|                 :tableData="tableData" | ||||
|                 :col-configs="colConfigs" | ||||
|                 :total="total" | ||||
|                 style="margin-top: 6px;" | ||||
|                 :border="true" | ||||
|                 :isShowPagination="false" | ||||
|                 @getList="() => {}"> | ||||
|               <el-table-column slot="options" width="160px" fixed="right" label="操作" align="center"> | ||||
|                 <template slot-scope="{ row, column, $index }"> | ||||
|                   <div class="table-options"> | ||||
|                     <el-button type="text" @click="toEdit(row.id, row.isCustom, row)">编辑</el-button> | ||||
|                     <el-button type="text" @click="toViewer(row.id)">预览</el-button> | ||||
|                     <el-button type="text" @click="remove($index)">删除</el-button> | ||||
|                   </div> | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|             </ai-table> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </el-form> | ||||
|       <Layout | ||||
|           v-if="isShowLayout" | ||||
|           :instance="instance" | ||||
|           :dict="dict" | ||||
|           :params="query" | ||||
|           @change="onChange" | ||||
|           :urlPrefix="urlPrefix" | ||||
|           @close="isShowLayout = false"> | ||||
|       </Layout> | ||||
|       <ai-dv-wrapper :views="[{label: '返回'}]" @change="screenId = false" v-if="screenId" :title="form.name"> | ||||
|         <AppGigscreenViewer :urlPrefix="urlPrefix" :instance="instance" :dict="dict" :id="screenId"></AppGigscreenViewer> | ||||
|       </ai-dv-wrapper> | ||||
|       <ai-dialog :visible.sync="dialog" title="定制大屏" @closed="custom={}" @onConfirm="handleCustomizedDV"> | ||||
|         <el-form ref="CustomDVFrom" size="small" :model="custom" :rules="rules" label-width="80px"> | ||||
|           <el-form-item label="大屏标题" prop="title"> | ||||
|             <el-input v-model="custom.title" clearable placeholder="请填写"/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="选择大屏" prop="dv"> | ||||
|             <ai-select v-model="custom.dv" :selectList="dict.getDict('customizedDVs')"/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="静态数据"> | ||||
|             <el-input type="textarea" rows="5" v-model="custom.meta"/> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button @click="cancel">取消</el-button> | ||||
|       <el-button type="primary" @click="confirm">提交</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AppGigscreenViewer from '../../viewer/AppGigscreenViewer' | ||||
| import Layout from './Layout.vue' | ||||
|  | ||||
| export default { | ||||
|   name: 'Add', | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     urlPrefix: String | ||||
|   }, | ||||
|  | ||||
|   components: { | ||||
|     Layout, | ||||
|     AppGigscreenViewer | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       info: {}, | ||||
|       department: [], | ||||
|       form: { | ||||
|         name: '', | ||||
|         relationLsIds: '', | ||||
|         relationLsNames: '', | ||||
|         status: '1', | ||||
|         description: '' | ||||
|       }, | ||||
|       screenId: '', | ||||
|       query: {}, | ||||
|       total: 0, | ||||
|       colConfigs: [ | ||||
|         {prop: 'title', label: '标题'}, | ||||
|         {prop: 'id', label: 'ID'} | ||||
|       ], | ||||
|       tableData: [], | ||||
|       isShowLayout: false, | ||||
|       id: '', | ||||
|       dialog: false, | ||||
|       custom: {}, | ||||
|       rules: { | ||||
|         dv: [{required: true, message: "请选择 定制大屏"}], | ||||
|         title: [{required: true, message: "请输入 大屏标题"}], | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     this.dict.load('customizedDVs') | ||||
|     if (this.params && this.params.id) { | ||||
|       this.id = this.params.id | ||||
|       this.getInfo(this.params.id) | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getInfo(id) { | ||||
|       this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenProjectDetailById?id=${id}`).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           this.form = { | ||||
|             ...res.data | ||||
|           } | ||||
|  | ||||
|           if (res.data.relationLsIds) { | ||||
|             this.tableData = res.data.lsList.map(v => { | ||||
|               let conf = JSON.parse(v.config || '') || {} | ||||
|               return { | ||||
|                 id: v.id, | ||||
|                 title: v.title, | ||||
|                 dv: conf.custom || '', | ||||
|                 meta: JSON.stringify(conf.meta), | ||||
|                 isCustom: !!conf.custom | ||||
|               } | ||||
|             }) | ||||
|             this.total = res.data.lsList.length | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     toViewer(id) { | ||||
|       this.screenId = id | ||||
|     }, | ||||
|  | ||||
|     getList() { | ||||
|       this.instance.post(`${this.urlPrefix}/appdiylargescreen/allLargeScreenByPage`, null, { | ||||
|         params: { | ||||
|           current: 1, | ||||
|           size: 1000 | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.tableData = res.data.records | ||||
|           this.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onChange(e) { | ||||
|       const ids = this.tableData.map(v => v.id) | ||||
|       if (ids.indexOf(e.id) < 0) { | ||||
|         this.tableData.push({ | ||||
|           title: e.title, | ||||
|           id: e.id | ||||
|         }) | ||||
|       } else { | ||||
|         const index = this.tableData.findIndex(v => v.id === e.id) | ||||
|         this.$set(this.tableData[index], 'title', e.title) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     add() { | ||||
|       this.query = { | ||||
|         id: '', | ||||
|         name: this.form.name | ||||
|       } | ||||
|       this.isShowLayout = true | ||||
|     }, | ||||
|  | ||||
|     toEdit(id, isCustom, form) { | ||||
|       if (!isCustom) { | ||||
|         this.query = { | ||||
|           id, | ||||
|           name: this.form.name | ||||
|         } | ||||
|  | ||||
|         this.isShowLayout = true | ||||
|       } else { | ||||
|         this.dialog = true | ||||
|         this.custom = { | ||||
|           ...form, | ||||
|  | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     remove(index) { | ||||
|       this.tableData.splice(index, 1) | ||||
|     }, | ||||
|  | ||||
|     confirm() { | ||||
|       this.$refs.form.validate((valid) => { | ||||
|         if (valid) { | ||||
|           const ids = this.tableData.map(v => v.id).join(',') | ||||
|           const names = this.tableData.map(v => v.name).join(',') | ||||
|           this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreenProject`, { | ||||
|             ...this.form, | ||||
|             relationLsIds: ids, | ||||
|             relationLsNames: names | ||||
|           }).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('提交成功') | ||||
|               setTimeout(() => { | ||||
|                 this.cancel(true) | ||||
|               }, 600) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     cancel(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: !!isRefresh | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     handleCustomizedDV() { | ||||
|       this.$refs.CustomDVFrom.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreen`, { | ||||
|             config: JSON.stringify({ | ||||
|               custom: this.custom.dv, | ||||
|               meta: JSON.parse(this.custom.meta?.replace(/\\n/g, '') || null) | ||||
|             }), | ||||
|             status: 1, | ||||
|             id: this.custom.id, | ||||
|             title: this.custom.title, | ||||
|           }).then(res => { | ||||
|             if (res?.code == 0 && res?.data) { | ||||
|               this.$message.success('保存成功') | ||||
|               this.onChange(res.data) | ||||
|               this.dialog = false | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| </style> | ||||
							
								
								
									
										92
									
								
								packages/bigscreen/designer/components/AiSwiper.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								packages/bigscreen/designer/components/AiSwiper.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| <template> | ||||
|   <div class="swiper"> | ||||
|     <el-carousel height="100%" indicator-position="none"> | ||||
|       <el-carousel-item v-for="(item, index) in data" :key="index"> | ||||
|         <img :src="item.img"> | ||||
|         <div class="swiper-content" v-if="item.title"> | ||||
|           <h2>{{ item.title }}</h2> | ||||
|           <p>{{ item.content }}</p> | ||||
|         </div> | ||||
|       </el-carousel-item> | ||||
|     </el-carousel> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'AiSwiper', | ||||
|  | ||||
|     props: { | ||||
|       data: { | ||||
|         type: Array, | ||||
|         default: () => [] | ||||
|       }, | ||||
|  | ||||
|       width: { | ||||
|         type: String, | ||||
|         default: '100%' | ||||
|       }, | ||||
|       heigth: { | ||||
|         type: String, | ||||
|         default: '100%' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|  | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|  | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|  | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .swiper { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     padding: 20px 0 0; | ||||
|  | ||||
|     ::v-deep .el-carousel { | ||||
|       height: 100%; | ||||
|     } | ||||
|  | ||||
|     img { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|     } | ||||
|  | ||||
|     .swiper-content { | ||||
|       position: absolute; | ||||
|       bottom: 0; | ||||
|       left: 0; | ||||
|       z-index: 1; | ||||
|       width: 100%; | ||||
|       padding: 10px; | ||||
|       text-align: center; | ||||
|       background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, #000000 100%); | ||||
|  | ||||
|       h2 { | ||||
|         margin-bottom: 4px; | ||||
|         color: #fff; | ||||
|         text-align: center; | ||||
|         font-size: 18px; | ||||
|       } | ||||
|  | ||||
|       p { | ||||
|         line-height: 22px; | ||||
|         white-space: pre-line; | ||||
|         color: #B6DFFF; | ||||
|         font-size: 14px; | ||||
|         text-align: center; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										1104
									
								
								packages/bigscreen/designer/components/Layout.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1104
									
								
								packages/bigscreen/designer/components/Layout.vue
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										141
									
								
								packages/bigscreen/designer/components/List.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								packages/bigscreen/designer/components/List.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| <template> | ||||
|   <ai-list class="form-list" isTabs style="width: 100%"> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar> | ||||
|         <template #left> | ||||
|           <ai-select | ||||
|             v-model="search.status" | ||||
|             @change="search.current = 1, getList()" | ||||
|             placeholder="发布状态" | ||||
|             :selectList="dict.getDict('questionnaireStatus')"> | ||||
|           </ai-select> | ||||
|           <el-button type="primary" @click="toEdit('')">添加大屏</el-button> | ||||
|           <el-button type="primary" @click="toAddData">数据源管理</el-button> | ||||
|         </template> | ||||
|         <template #right> | ||||
|           <el-input | ||||
|             v-model="search.title" | ||||
|             size="small" | ||||
|             placeholder="请输入模板名称或创建人" | ||||
|             clearable | ||||
|             @keyup.enter.native="search.current = 1, getList()" | ||||
|             @clear="search.current = 1, search.title = '', getList()" | ||||
|             suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table | ||||
|         :tableData="tableData" | ||||
|         :col-configs="colConfigs" | ||||
|         :total="total" | ||||
|         v-loading="loading" | ||||
|         style="margin-top: 6px;" | ||||
|         :current.sync="search.current" | ||||
|         :size.sync="search.size" | ||||
|         @getList="getList"> | ||||
|         <el-table-column slot="options" width="120px" fixed="right" label="操作" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-options"> | ||||
|               <el-button type="text" @click="toEdit(row.id)">编辑</el-button> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'FormList', | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       areaId: String, | ||||
|       urlPrefix: String | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         search: { | ||||
|           current: 1, | ||||
|           status: '', | ||||
|           size: 10, | ||||
|           title: '' | ||||
|         }, | ||||
|         colConfigs: [ | ||||
|           { prop: 'name', label: '模板名称' }, | ||||
|           { prop: 'createUserName', align: 'center', label: '创建人' }, | ||||
|           { prop: 'description', align: 'center', label: '描述' }, | ||||
|           { prop: 'status', align: 'center', label: '状态', formart: v => v === '1' ? '已开启' : '未开启' }, | ||||
|           { prop: 'createTime', align: 'center', label: '创建时间' } | ||||
|         ], | ||||
|         tableData: [], | ||||
|         total: 0, | ||||
|         loading: false | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|        | ||||
|       this.dict.load('questionnaireStatus').then(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.loading = true | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/allLargeScreenProjectByPage`, null, { | ||||
|           params: { | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|             this.loading = false | ||||
|           } else { | ||||
|             this.loading = false | ||||
|           } | ||||
|         }).catch(() => { | ||||
|           this.loading = false | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       toEdit (id) { | ||||
|         this.$emit('change', { | ||||
|           type: 'add', | ||||
|           params: { | ||||
|             id: id || '' | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       toAddData () { | ||||
|         this.$emit('change', { | ||||
|           type: 'SourceData' | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onConfirm () { | ||||
|         this.$emit('change', { | ||||
|           type: 'add', | ||||
|           params: { | ||||
|             id: '', | ||||
|             templateType: 0, | ||||
|             type: this.currIndex | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .form-list { | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										188
									
								
								packages/bigscreen/designer/components/RenderElement.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								packages/bigscreen/designer/components/RenderElement.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,188 @@ | ||||
| <template> | ||||
|   <div class="render-element" style="width: 100%; height: 100%;"> | ||||
|     <ai-dv-display v-if="data.type === 'display'" :title="data.title" :list="data[data.dataType]"></ai-dv-display> | ||||
|     <ai-dv-panel | ||||
|       style="height: 100%; width: 100%;" | ||||
|       v-if="data.type !== 'display'" | ||||
|       :title="data.title" | ||||
|       :border="data.border || ''"> | ||||
|       <AiDvSummary v-if="data.type === 'summary'" :key="`summary${index}`" :type="data.display" :data="data[data.dataType]"/> | ||||
|       <AiSwiper v-else-if="data.type === 'swiper'" :heigth="'100%'" :data="data[data.dataType]"/> | ||||
|       <dv-scroll-board | ||||
|         v-if="data.type === 'table'" | ||||
|         :config="formatTable(data[data.dataType], data.isShowIndex, data.rowNum)" | ||||
|         :key="data.height" | ||||
|         :style="{height: data.height + 'px', width: '100%'}" /> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'barChart1'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="data.config"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'barChart2'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="data.config"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'barChart3'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="data.config"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'barChart5'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="data.config"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'barChart7'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="data.config"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'barChart8'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="data.config"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'barChart9'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="data.config"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'lineChart1'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="lineChart1"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'lineChart2'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="lineChart2"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'lineChart3'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="data.config"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'lineChart4'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="data.config"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'lineChart5'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="lineChart5"/> | ||||
|       <ai-echart | ||||
|         v-else-if="data.type === 'pieChart'" | ||||
|         style="height: 100%; width: 100%;" | ||||
|         :ref="'chart' + index" | ||||
|         :key="`chart${index}`" | ||||
|         :data="data[data.dataType]" | ||||
|         :ops="pieChart"/> | ||||
|       <ai-map :markers="data[data.dataType]" v-else-if="data.type=='map'" :mask="data.mask === '1'" :areaId="data.areaId || user.info.areaId" map-style="amap://styles/e51987628aee5206d4c9ca8c6e98b4f7"/> | ||||
|       <ai-monitor :src="data.src" v-else-if="data.type === 'monitor'" :type="data.monitorType"></ai-monitor> | ||||
|       <video style="width: 100%; height: 100%; object-fit: fill;" loop :src="data.src" autoplay v-else-if="data.type === 'video'"></video> | ||||
|     </ai-dv-panel> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import { mapState } from 'vuex' | ||||
|   import AiSwiper from './AiSwiper.vue' | ||||
|   import pieChart from 'dvcp-dv-ui/components/AiEchart/template/pie/pieChart2' | ||||
|   import lineChart1 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart1' | ||||
|   import lineChart2 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart2' | ||||
|   import lineChart5 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart5' | ||||
|  | ||||
|   export default { | ||||
|     name: 'RenderElement', | ||||
|  | ||||
|     props: ['data', 'index'], | ||||
|  | ||||
|     components: { | ||||
|       AiSwiper | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         lineChart1, | ||||
|         lineChart2, | ||||
|         lineChart5, | ||||
|         pieChart | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       ...mapState(['user']) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       formatTable(data, isShowIndex, rowNum) { | ||||
|         if (!data.length) { | ||||
|           return { | ||||
|             header: [], | ||||
|             data: [] | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         let rows = [] | ||||
|         const header = data.map(v => { | ||||
|           return v[Object.keys(v)[0]] | ||||
|         }) | ||||
|  | ||||
|         Object.keys(data[0]).forEach((item, index) => { | ||||
|           if (index !== 0) { | ||||
|             rows.push(item) | ||||
|           } | ||||
|         }) | ||||
|  | ||||
|         return { | ||||
|           header: header, | ||||
|           data: rows.map(item => { | ||||
|             return data.map(v => { | ||||
|               return v[item] | ||||
|             }) | ||||
|           }), | ||||
|           headerBGC: 'transparent', | ||||
|           evenRowBGC: 'transparent', | ||||
|           oddRowBGC: 'rgba(0, 133, 255, 0.2)', | ||||
|           headerHeight: 42, | ||||
|           rowNum: rowNum || 7, | ||||
|           index: isShowIndex === '1', | ||||
|           carousel: 'page', | ||||
|           indexHeader: '排名', | ||||
|           align: ['center', 'center', 'center', 'center', 'center'] | ||||
|         } | ||||
|       }, | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|  | ||||
| </style> | ||||
							
								
								
									
										430
									
								
								packages/bigscreen/designer/components/SourceData.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										430
									
								
								packages/bigscreen/designer/components/SourceData.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,430 @@ | ||||
| <template> | ||||
|   <ai-detail> | ||||
|     <template slot="title"> | ||||
|       <ai-title title="数据源" isShowBack isShowBottomBorder @onBackClick="cancel(false)"> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-card title="数据源列表"> | ||||
|         <template #right> | ||||
|           <el-button type="primary" @click="isShow = true">添加数据源</el-button> | ||||
|         </template> | ||||
|         <template #content> | ||||
|           <ai-search-bar class="search-bar"> | ||||
|             <template slot="right"> | ||||
|               <el-input | ||||
|                 v-model="search.name" | ||||
|                 size="small" | ||||
|                 @keyup.enter.native="search.current = 1, getList()" | ||||
|                 placeholder="请输入名字" | ||||
|                 clearable | ||||
|                 @clear="search.current = 1, search.name = '', getList()" | ||||
|                 suffix-icon="iconfont iconSearch"> | ||||
|               </el-input> | ||||
|             </template> | ||||
|           </ai-search-bar> | ||||
|           <ai-table | ||||
|             :tableData="tableData" | ||||
|             :col-configs="colConfigs" | ||||
|             :total="total" | ||||
|             style="margin-top: 6px;" | ||||
|             :border="true" | ||||
|             :current.sync="search.current" | ||||
|             :size.sync="search.size" | ||||
|             @getList="getList"> | ||||
|             <el-table-column slot="options" width="160px" fixed="right" label="操作" align="center"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 <div class="table-options"> | ||||
|                   <el-button type="text" @click="toEdit(row)">编辑</el-button> | ||||
|                   <el-button type="text" @click="remove(row.id)">删除</el-button> | ||||
|                 </div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       <ai-dialog | ||||
|         :visible.sync="isShow" | ||||
|         width="820px" | ||||
|         title="数据源" | ||||
|         @close="onClose" | ||||
|         @onConfirm="onConfirm"> | ||||
|         <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|           <div class="ai-form"> | ||||
|             <el-form-item label="数据源描述" style="width: 100%;" prop="description" :rules="[{ required: true, message: '请输入数据源描述', trigger: 'blur' }]"> | ||||
|               <el-input | ||||
|                 size="small" | ||||
|                 placeholder="请输入数据源描述" | ||||
|                 v-model="form.description"> | ||||
|               </el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="村微应用" style="width: 100%;" prop="appId" :rules="[{ required: true, message: '请选择村微应用', trigger: 'change' }]"> | ||||
|               <el-select size="small" style="width: 100%;" v-model="form.appId" placeholder="请选择村微应用" @change="onAppChange"> | ||||
|                 <el-option | ||||
|                   v-for="item in appList" | ||||
|                   :key="item.id" | ||||
|                   :label="item.appName" | ||||
|                   :value="item.id"> | ||||
|                 </el-option> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="数据范围" style="width: 100%;" prop="dataRange" :rules="[{ required: true, message: '请选择数据范围', trigger: 'change' }]"> | ||||
|               <el-radio-group v-model="form.dataRange"> | ||||
|                 <el-radio label="0">全部</el-radio> | ||||
|                 <el-radio label="1">自定义条数</el-radio> | ||||
|               </el-radio-group> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="数据条数" style="width: 100%;" v-if="form.dataRange === '1'" prop="count" :rules="[{ required: true, message: '请输入数据条数', trigger: 'blur' }]"> | ||||
|               <el-input | ||||
|                 size="small" | ||||
|                 placeholder="请输入数据条数" | ||||
|                 v-model="form.count"> | ||||
|               </el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item :label="'统计项' + index" style="width: 100%;" v-for="(item, index) in form.statisticsConfigs" :key="'statisticsConfigs' + index"> | ||||
|               <div class="form-flex"> | ||||
|                 <div> | ||||
|                   <el-select size="small" style="width: 160px;" v-model="item.fieldName" @change="e => onChooseField('statisticsConfigs', e, index)" placeholder="请选择" clearable> | ||||
|                     <el-option | ||||
|                       v-for="(item, index) in filedList" | ||||
|                       :key="index" | ||||
|                       :label="item.fieldCnName" | ||||
|                       :value="item.fieldName"> | ||||
|                     </el-option> | ||||
|                   </el-select> | ||||
|                   <el-select size="small" style="margin: 0 10px; width: 160px;" v-model="item.calcType" placeholder="请选择" clearable> | ||||
|                     <el-option | ||||
|                       v-for="item in dict.getDict('diyLargeScreenDatasourceCalcType2')" | ||||
|                       :key="item.id" | ||||
|                       :label="item.dictName" | ||||
|                       :value="item.dictValue"> | ||||
|                     </el-option> | ||||
|                   </el-select> | ||||
|                   <el-input size="small" style="width: 165px;" placeholder="请输入别名" v-model="item.alias"></el-input> | ||||
|                 </div> | ||||
|                 <el-button type="danger" v-if="index > 0" @click="removeConfig('statisticsConfigs', index)">删除</el-button> | ||||
|               </div> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%;"> | ||||
|               <el-button type="primary" @click="add('statisticsConfigs')">添加统计项</el-button> | ||||
|             </el-form-item> | ||||
|             <el-form-item :label="'分组' + index" style="width: 100%;" v-for="(item, index) in form.groupConfigs" :key="'groupConfigs' + item.fieldName"> | ||||
|               <div class="form-flex"> | ||||
|                 <div> | ||||
|                   <el-select size="small" style="width: 160px;" v-model="item.fieldName" placeholder="请选择" clearable> | ||||
|                     <el-option | ||||
|                       v-for="item in filedList" | ||||
|                       :key="item.id" | ||||
|                       :label="item.fieldCnName" | ||||
|                       :value="item.fieldName"> | ||||
|                     </el-option> | ||||
|                   </el-select> | ||||
|                 </div> | ||||
|                 <el-button type="danger" @click="removeConfig('groupConfigs', index)">删除</el-button> | ||||
|               </div> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%;"> | ||||
|               <el-button type="primary" @click="add('groupConfigs')">添加分组</el-button> | ||||
|             </el-form-item> | ||||
|             <el-form-item :label="'统计项' + index" style="width: 100%;" v-for="(item, index) in form.orderConfigs" :key="'orderConfigs' + item.fieldName"> | ||||
|               <div class="form-flex"> | ||||
|                 <div> | ||||
|                   <el-select size="small" style="width: 160px;" v-model="item.fieldName" placeholder="请选择" clearable> | ||||
|                     <el-option | ||||
|                       v-for="item in filedList" | ||||
|                       :key="item.id" | ||||
|                       :label="item.fieldCnName" | ||||
|                       :value="item.fieldName"> | ||||
|                     </el-option> | ||||
|                   </el-select> | ||||
|                   <el-select size="small" style="width: 160px; margin-left: 10px;" v-model="item.orderType" placeholder="请选择" clearable> | ||||
|                     <el-option | ||||
|                       v-for="item in orderTypeDict" | ||||
|                       :key="item.id" | ||||
|                       :label="item.label" | ||||
|                       :value="item.value"> | ||||
|                     </el-option> | ||||
|                   </el-select> | ||||
|                 </div> | ||||
|                 <el-button type="danger" @click="removeConfig('orderConfigs', index)">删除</el-button> | ||||
|               </div> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%;"> | ||||
|               <el-button type="primary" @click="add('orderConfigs')">添加排序</el-button> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'SourceData', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       params: Object, | ||||
|       urlPrefix: String | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         isShow: false, | ||||
|         search: { | ||||
|           current: 1, | ||||
|           size: 10, | ||||
|           name: '' | ||||
|         }, | ||||
|         total: 0, | ||||
|         colConfigs: [ | ||||
|           { prop: 'appName', label: '应用名' }, | ||||
|           { prop: 'appTableName', label: '表名' }, | ||||
|           { prop: 'createUserName', label: '创建人' }, | ||||
|           { prop: 'description', label: '描述' }, | ||||
|           { prop: 'createTime', align: 'center', label: '创建时间' } | ||||
|         ], | ||||
|         tableData: [], | ||||
|         filedList: [], | ||||
|         appList: [], | ||||
|         form: { | ||||
|           orderType: 'asc', | ||||
|           dataRange: '0', | ||||
|           appId: '', | ||||
|           description: '', | ||||
|           appName: '', | ||||
|           appTableName: '', | ||||
|           count: '100', | ||||
|           statisticsConfigs: [{ | ||||
|             alias: '', | ||||
|             calcType: '', | ||||
|             dictCode: '', | ||||
|             fieldCnName: '', | ||||
|             fieldName: '' | ||||
|           }], | ||||
|           orderConfigs: [{ | ||||
|             alias: '', | ||||
|             calcType: '', | ||||
|             dictCode: '', | ||||
|             fieldCnName: '', | ||||
|             fieldName: '' | ||||
|           }], | ||||
|           groupConfigs: [{ | ||||
|             alias: '', | ||||
|             calcType: '', | ||||
|             dictCode: '', | ||||
|             fieldCnName: '', | ||||
|             fieldName: '' | ||||
|           }] | ||||
|         }, | ||||
|         id: '', | ||||
|         orderTypeDict: [ | ||||
|           { | ||||
|             value: 'asc', | ||||
|             label: '升序' | ||||
|           }, | ||||
|           { | ||||
|             value: 'desc', | ||||
|             label: '降序' | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.dict.load(['diyLargeScreenDatasourceCalcType2']).then(() => { | ||||
|         this.getList() | ||||
|         this.getAppList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getInfo (id) { | ||||
|         this.instance.post(`${this.urlPrefix}/wxcp/wxuser/queryDetailById?id=${id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.form = { | ||||
|               ...res.data | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onChooseField (type, fieldName, index) { | ||||
|         const dictCode = this.filedList.filter(v => v.fieldName === fieldName)[0].dictCode | ||||
|         this.$set(this.form[type][index], 'dictCode', dictCode) | ||||
|       }, | ||||
|  | ||||
|       add (type) { | ||||
|         this.form[type].push({ | ||||
|           alias: '', | ||||
|           calcType: '', | ||||
|           dictCode: '', | ||||
|           fieldCnName: '', | ||||
|           fieldName: '' | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       removeConfig (type, index) { | ||||
|         this.form[type].splice(index, 1) | ||||
|       }, | ||||
|  | ||||
|       toEdit (e) { | ||||
|         this.id = e.id | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryDatasourceDetailById?id=${e.id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.form = { | ||||
|               ...res.data | ||||
|             } | ||||
|             this.form.dataRange = this.form.dataRange === '0' ? '0' : '1' | ||||
|             this.form.count = res.data.dataRange | ||||
|             this.filedList = this.appList.filter(v => v.id === res.data.appId)[0].fields.map(item => { | ||||
|               let value = [] | ||||
|               res.data.configs.forEach(v => { | ||||
|                 if (v.fieldName === item.fieldName) { | ||||
|                   value.push(v.calcType) | ||||
|                 } | ||||
|               }) | ||||
|  | ||||
|               return { | ||||
|                 ...item, | ||||
|                 value | ||||
|               } | ||||
|             }) | ||||
|  | ||||
|             this.isShow = true | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       remove (id) { | ||||
|         this.$confirm('确定删除该数据?').then(() => { | ||||
|           this.instance.post(`${this.urlPrefix}/appquestionnairetemplate/delete?id=${id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getList () { | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/allDatasourceByPage`, null, { | ||||
|           params: { | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getAppList () { | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/allDatasourceApp`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.appList = res.data | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onClose () { | ||||
|         this.id = '' | ||||
|         this.form.orderType = 'asc' | ||||
|         this.form.dataRange = 0 | ||||
|         this.form.appId = '' | ||||
|         this.form.description = '' | ||||
|         this.form.appName = '' | ||||
|         this.form.appTableName = '' | ||||
|         this.form.count = 100 | ||||
|       }, | ||||
|  | ||||
|       onAppChange (e) { | ||||
|         const value = this.appList.filter(v => v.id === e)[0] | ||||
|         this.form.appTableName = value.appTableName | ||||
|         this.form.appName = value.appName | ||||
|         this.form.statisticsConfigs = [{ | ||||
|           alias: '', | ||||
|           calcType: '', | ||||
|           dictCode: '', | ||||
|           fieldCnName: '', | ||||
|           fieldName: '' | ||||
|         }] | ||||
|         this.form.orderConfigs = [{ | ||||
|           alias: '', | ||||
|           calcType: '', | ||||
|           dictCode: '', | ||||
|           fieldCnName: '', | ||||
|           fieldName: '' | ||||
|         }] | ||||
|         this.form.groupConfigs = [{ | ||||
|           alias: '', | ||||
|           calcType: '', | ||||
|           dictCode: '', | ||||
|           fieldCnName: '', | ||||
|           fieldName: '' | ||||
|         }] | ||||
|         this.filedList = value.fields.map(v => { | ||||
|           return { | ||||
|             ...v, | ||||
|             value: '' | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onConfirm () { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             let configs = [] | ||||
|             this.filedList.forEach(item => { | ||||
|               if (item.value.length) { | ||||
|                 item.value.forEach(v => { | ||||
|                   configs.push({ | ||||
|                     alias: item.fieldCnName, | ||||
|                     calcType: v, | ||||
|                     fieldCnName: item.fieldCnName, | ||||
|                     fieldName: item.fieldName, | ||||
|                     dictCode: item.dictCode, | ||||
|                     orderType: this.orderType | ||||
|                   }) | ||||
|                 }) | ||||
|               } | ||||
|             }) | ||||
|  | ||||
|             this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateDatasource`, { | ||||
|               ...this.form, | ||||
|               configs, | ||||
|               id: this.id ? this.id : '', | ||||
|               dataRange: this.form.dataRange === '0' ? 0 : this.form.count | ||||
|             }).then(res => { | ||||
|               if (res.code === 0) { | ||||
|                 this.$message.success(this.id ? '编辑成功' : '添加成功') | ||||
|                 this.search.current = 1 | ||||
|                 this.isShow = false | ||||
|  | ||||
|                 this.getList() | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       cancel (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'list', | ||||
|           isRefresh: !!isRefresh | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .form-flex { | ||||
|     display: flex; | ||||
|     justify-content: space-between; | ||||
|     align-items: center; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										455
									
								
								packages/bigscreen/designer/components/form/DataConfig.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										455
									
								
								packages/bigscreen/designer/components/form/DataConfig.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,455 @@ | ||||
| <template> | ||||
|   <div class="layout-config__group--wrapper"> | ||||
|     <ai-dialog | ||||
|       append-to-body | ||||
|       :visible.sync="isShowEditor" | ||||
|       width="1000px" | ||||
|       class="layout-config__edit" | ||||
|       title="编辑器" | ||||
|       @onConfirm="onConfirm"> | ||||
|       <div style="height: 500px;"> | ||||
|         <vue-json-editor | ||||
|           v-model="json"  | ||||
|           :show-btns="false" | ||||
|           mode="code" | ||||
|           lang="zh"> | ||||
|         </vue-json-editor> | ||||
|       </div> | ||||
|     </ai-dialog> | ||||
|     <div class="layout-config__group" v-if="options.monitorType !== 'hik'"> | ||||
|       <h2>基础设置</h2> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>数据类型</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" v-model="options.dataType" placeholder="请选择数据类型"> | ||||
|             <el-option | ||||
|               v-for="item in dataTypes" | ||||
|               :key="item.value" | ||||
|               :label="item.label" | ||||
|               :value="item.value"> | ||||
|             </el-option> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__code" v-if="options.dataType === 'staticData'"> | ||||
|         <el-button @click="showEditor" class="layout-config__code--btn" title="编辑" type="text" icon="iconfont iconjdq_led_edit"></el-button> | ||||
|         <vue-json-editor | ||||
|           :value="options.staticData"  | ||||
|           :show-btns="false" | ||||
|           mode="view" | ||||
|           lang="zh"> | ||||
|         </vue-json-editor> | ||||
|       </div> | ||||
|       <template v-else-if="options.dataType === 'dynamicData'"> | ||||
|         <div class="layout-config__item"> | ||||
|           <label>数据源</label> | ||||
|           <div class="layout-config__item--right"> | ||||
|             <el-select size="mini" v-model="options.sourceDataId" placeholder="请选择数据源" @change="onDataChange"> | ||||
|               <el-option | ||||
|                 v-for="item in sourceData" | ||||
|                 :key="item.id" | ||||
|                 :label="item.description" | ||||
|                 :value="item.id"> | ||||
|               </el-option> | ||||
|             </el-select> | ||||
|           </div> | ||||
|         </div> | ||||
|       </template> | ||||
|       <template v-else> | ||||
|         <div class="layout-config__item"> | ||||
|           <label>接口地址</label> | ||||
|           <div class="layout-config__item--right"> | ||||
|             <el-input size="mini" v-model="options.api" @blur="onApiChange"></el-input> | ||||
|           </div> | ||||
|         </div> | ||||
|       </template> | ||||
|     </div> | ||||
|     <div class="layout-config__group" v-if="options.monitorType === 'hik'"> | ||||
|       <h2>基础设置</h2> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>视频ID</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-input size="mini" v-model="options.src"></el-input> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="layout-config__group" v-if="options.dataType !== 'staticData' && options.type === 'monitor' && options.monitorType === 'cmcc'"> | ||||
|       <h2>字段设置</h2> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>监控视频</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" v-model="options.moniterId" placeholder="请选择监控视频" @change="onMoniterId"> | ||||
|             <el-option | ||||
|               v-for="(item, index) in monitorList" | ||||
|               :key="index" | ||||
|               :label="item.name" | ||||
|               :value="item.id"> | ||||
|             </el-option> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="layout-config__group" v-if="options.dataType !== 'staticData' && options.type !== 'monitor' && keys.length && options.type !== 'table'"> | ||||
|       <h2>字段设置</h2> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>X轴设置</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" v-model="options.dataX" placeholder="请选择X轴" @change="onChooseChange"> | ||||
|             <el-option | ||||
|               v-for="(item, index) in keys" | ||||
|               :key="index" | ||||
|               :label="item" | ||||
|               :value="item"> | ||||
|             </el-option> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>Y轴设置</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" multiple :multiple-limit="options.type.indexOf('pie') > -1 ? 1 : 100" v-model="options.dataY" collapse-tags placeholder="请选择Y轴" @change="onChooseChange"> | ||||
|             <el-option | ||||
|               v-for="(item, index) in keys" | ||||
|               :key="index" | ||||
|               :label="item" | ||||
|               :value="item"> | ||||
|             </el-option> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import vueJsonEditor from 'vue-json-editor' | ||||
|   export default { | ||||
|     name: 'dataCofing', | ||||
|  | ||||
|     props: { | ||||
|       options: Object, | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       params: Object, | ||||
|       urlPrefix: String | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         dataTypes: [ | ||||
|           { | ||||
|             value: 'staticData', | ||||
|             label: '静态数据' | ||||
|           }, | ||||
|           { | ||||
|             value: 'dynamicData', | ||||
|             label: '动态数据' | ||||
|           }, | ||||
|           { | ||||
|             value: 'apiData', | ||||
|             label: '接口' | ||||
|           } | ||||
|         ], | ||||
|         isShowEditor: false, | ||||
|         json: {}, | ||||
|         sourceDataId: '', | ||||
|         sourceData: [], | ||||
|         keys: [], | ||||
|         monitorList: [], | ||||
|         list: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       vueJsonEditor | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.getDataList() | ||||
|  | ||||
|       if ((this.options.dataY && this.options.dataY.length && this.options.dataX) || this.options.type === 'monitor') { | ||||
|         const api = this.options.dataType === 'apiData' ? this.options.api : `${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${this.options.sourceDataId}` | ||||
|         this.instance.post(api).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             if (res.data.length && this.options.type !== 'monitor') { | ||||
|               this.list = res.data | ||||
|               this.keys = Object.keys(res.data[0]) | ||||
|  | ||||
|               this.$nextTick(() => { | ||||
|                 this.onChooseChange() | ||||
|               }) | ||||
|             } else if (this.options.type === 'monitor') { | ||||
|               this.monitorList = res.data | ||||
|  | ||||
|               if (this.options.src) { | ||||
|                 const obj = res.data.filter(v => this.options.title === v.name) | ||||
|  | ||||
|                 if (obj.length) { | ||||
|                   this.options.src = obj[0].url | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       showEditor () { | ||||
|         this.json = JSON.parse(JSON.stringify(this.options.staticData)) | ||||
|         this.isShowEditor = true | ||||
|       }, | ||||
|  | ||||
|       onMoniterId (e) { | ||||
|         this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${e}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.options.src = JSON.parse(res.data).url | ||||
|           } | ||||
|         }) | ||||
|       },  | ||||
|  | ||||
|       getDataList () { | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/allDatasourceByPage`, null, { | ||||
|           params: { | ||||
|             current: 1, | ||||
|             size: 10000 | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.sourceData = res.data.records | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onApiChange () { | ||||
|         this.options.dataX = '' | ||||
|         this.options.dataY = [] | ||||
|         this.instance.post(this.options.api).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             if (res.data.length) { | ||||
|               if (this.options.type === 'table') { | ||||
|                 const keys = Object.keys(res.data[0]) | ||||
|                 const list = res.data | ||||
|                 this.options.apiData = keys.map(v => { | ||||
|                   let obj = {} | ||||
|                   list.forEach((item, index) => { | ||||
|                     obj[`v${index}`] = item[v] | ||||
|                   }) | ||||
|  | ||||
|                   return { | ||||
|                     row: v, | ||||
|                     ...obj | ||||
|                   } | ||||
|                 }) | ||||
|               } else if (this.options.type === 'summary') { | ||||
|                 this.options.apiData = Object.keys(res.data[0]).map(item => { | ||||
|                   return { | ||||
|                     key: item, | ||||
|                     value: res.data[0][item] | ||||
|                   } | ||||
|                 }) | ||||
|               } else if (this.options.type === 'monitor') { | ||||
|                 this.monitorList = res.data | ||||
|               } else { | ||||
|                 this.list = res.data | ||||
|                 this.keys = Object.keys(res.data[0]) | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onChooseChange () { | ||||
|         let arr = [] | ||||
|         if (this.options.dataX && this.options.dataY.length) { | ||||
|           this.list.forEach(item => { | ||||
|             let obj = {} | ||||
|             this.options.dataY.forEach(v => { | ||||
|               obj[v] = item[v] | ||||
|             }) | ||||
|             arr.push({ | ||||
|               [this.options.dataX]: item[this.options.dataX], | ||||
|               ...obj | ||||
|             }) | ||||
|           }) | ||||
|  | ||||
|           this.options[this.options.dataType] = arr | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       onDataChange (e) { | ||||
|         this.options.dataX = '' | ||||
|         this.options.dataY = [] | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${e}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             if (res.data.length) { | ||||
|               if (this.options.type === 'table') { | ||||
|                 const keys = Object.keys(res.data[0]) | ||||
|                 const list = res.data | ||||
|                 this.options.dynamicData = keys.map(v => { | ||||
|                   let obj = {} | ||||
|                   list.forEach((item, index) => { | ||||
|                     obj[`v${index}`] = item[v] | ||||
|                   }) | ||||
|  | ||||
|                   return { | ||||
|                     row: v, | ||||
|                     ...obj | ||||
|                   } | ||||
|                 }) | ||||
|               } else if (this.options.type === 'summary') { | ||||
|                 this.options.dynamicData = Object.keys(res.data[0]).map(item => { | ||||
|                   return { | ||||
|                     key: item, | ||||
|                     value: res.data[0][item] | ||||
|                   } | ||||
|                 }) | ||||
|               } else { | ||||
|                 this.list = res.data | ||||
|                 this.keys = Object.keys(res.data[0]) | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onConfirm () { | ||||
|         this.$set(this.options, 'staticData', JSON.parse(JSON.stringify(this.json))) | ||||
|         this.isShowEditor = false | ||||
|         this.$emit('change') | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
|    .el-dialog__body { | ||||
|       .jsoneditor-vue { | ||||
|         height: 480px; | ||||
|  | ||||
|         .jsoneditor-poweredBy { | ||||
|           display: none; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   .layout-config__group--wrapper { | ||||
|     .layout-config__code .jsoneditor-vue { | ||||
|       .jsoneditor-menu { | ||||
|         display: none; | ||||
|       } | ||||
|  | ||||
|       .jsoneditor { | ||||
|         border: 1px solid #030411; | ||||
|         background: #0e1013; | ||||
|       } | ||||
|  | ||||
|       .jsoneditor-field { | ||||
|         color: gray; | ||||
|       } | ||||
|  | ||||
|       .jsoneditor-tree button:focus { | ||||
|         background-color: transparent; | ||||
|         outline: none; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .layout-config__group { | ||||
|       padding: 10px 10px 20px; | ||||
|       border-bottom: 1px solid #000000; | ||||
|  | ||||
|       &:last-child { | ||||
|         border: none; | ||||
|       } | ||||
|  | ||||
|       .layout-config__code { | ||||
|         position: relative; | ||||
|         padding-left: 10px; | ||||
|  | ||||
|         .layout-config__code--btn { | ||||
|           position: absolute; | ||||
|           right: 0; | ||||
|           top: 0; | ||||
|           color: gray; | ||||
|           z-index: 1; | ||||
|  | ||||
|           &:hover { | ||||
|             opacity: 0.8  ; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       & > h2 { | ||||
|         margin-bottom: 20px; | ||||
|         color: #FFFFFF; | ||||
|         font-size: 15px; | ||||
|         font-weight: 700; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .layout-config__item { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
|       margin-bottom: 10px; | ||||
|  | ||||
|       &:last-child { | ||||
|         margin-bottom: 0; | ||||
|       } | ||||
|  | ||||
|       label { | ||||
|         flex-shrink: 0; | ||||
|         width: 60px; | ||||
|         color: #FFFFFF; | ||||
|         font-size: 12px; | ||||
|         text-align: right; | ||||
|       } | ||||
|  | ||||
|       .layout-config__item--right { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         justify-content: flex-end; | ||||
|         width: 200px; | ||||
|         text-align: right; | ||||
|       } | ||||
|  | ||||
|       .el-select .el-tag { | ||||
|         color: #fff; | ||||
|         background: transparent; | ||||
|       } | ||||
|  | ||||
|       input { | ||||
|         background: #262C33; | ||||
|         font-size: 12px; | ||||
|         color: #fff; | ||||
|         border: 1px solid #030411; | ||||
|       } | ||||
|  | ||||
|       .el-input__icon { | ||||
|         color: #fff; | ||||
|       } | ||||
|  | ||||
|       .el-switch__label { | ||||
|         color: #fff; | ||||
|       } | ||||
|  | ||||
|       .el-select { | ||||
|         width: 100%; | ||||
|  | ||||
|         &:last-child { | ||||
|           margin-right: 0; | ||||
|         } | ||||
|  | ||||
|         input { | ||||
|           background: #262C33; | ||||
|           font-size: 12px; | ||||
|           color: #fff; | ||||
|           border: 1px solid #030411; | ||||
|         } | ||||
|  | ||||
|         .el-input__icon { | ||||
|           color: #fff; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										637
									
								
								packages/bigscreen/designer/config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										637
									
								
								packages/bigscreen/designer/config.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,637 @@ | ||||
| import lineChart1 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart1' | ||||
| import lineChart2 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart2' | ||||
| import lineChart3 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart3' | ||||
| import lineChart4 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart4' | ||||
| import lineChart5 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart5' | ||||
| import barChart1 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart1' | ||||
| import barChart2 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart2' | ||||
| import barChart3 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart3' | ||||
| import barChart8 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart8' | ||||
| import barChart5 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart5' | ||||
| import barChart7 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart7' | ||||
| import barChart9 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart9' | ||||
| import pieChart from 'dvcp-dv-ui/components/AiEchart/template/pie/pieChart2' | ||||
|  | ||||
| const components = [ | ||||
|   { | ||||
|     type: 'chart', | ||||
|     label: '图表', | ||||
|     list: [ | ||||
|       { | ||||
|         label: '柱状图', | ||||
|         type: 'bar', | ||||
|         list: [ | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'barChart1', | ||||
|             label: '柱状图1', | ||||
|             title: '柱状图', | ||||
|             border: 'border1', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar1.png', | ||||
|             width: 500, | ||||
|             sourceDataId: '', | ||||
|             height: 300, | ||||
|             dataX: '', | ||||
|             zIndex: 1, | ||||
|             dataY: [], | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23 }, | ||||
|               { name: '水电费', v1: 12 }, | ||||
|               { name: '凡哥', v1: 67 }, | ||||
|               { name: '党费', v1: 98 } | ||||
|             ], | ||||
|             config: barChart1, | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'barChart1', | ||||
|             label: '柱状图2', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             title: '柱状图2', | ||||
|             width: 500, | ||||
|             border: 'border1', | ||||
|             sourceDataId: '', | ||||
|             height: 300, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar2.png', | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             top: 0, | ||||
|             zIndex: 1, | ||||
|             left: 0, | ||||
|             dataType: 'staticData', | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23 }, | ||||
|               { name: '水电费', v1: 12 }, | ||||
|               { name: '凡哥', v1: 67 }, | ||||
|               { name: '党费', v1: 98 } | ||||
|             ], | ||||
|             config: barChart2, | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'barChart3', | ||||
|             label: '柱状图3', | ||||
|             title: '柱状图3', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             width: 500, | ||||
|             sourceDataId: '', | ||||
|             height: 300, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar3.png', | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             border: 'border1', | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             zIndex: 1, | ||||
|             dataType: 'staticData', | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23 }, | ||||
|               { name: '水电费', v1: 12 }, | ||||
|               { name: '凡哥', v1: 67 }, | ||||
|               { name: '党费', v1: 98 } | ||||
|             ], | ||||
|             config: barChart3, | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'barChart5', | ||||
|             label: '柱状图4', | ||||
|             title: '柱状图4', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             width: 500, | ||||
|             sourceDataId: '', | ||||
|             height: 300, | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             zIndex: 1, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar5.png', | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             border: 'border1', | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23 }, | ||||
|               { name: '水电费', v1: 12 }, | ||||
|               { name: '凡哥', v1: 67 }, | ||||
|               { name: '党费', v1: 98 } | ||||
|             ], | ||||
|             config: barChart5, | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'barChart7', | ||||
|             label: '柱状图5', | ||||
|             title: '柱状图5', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             width: 500, | ||||
|             sourceDataId: '', | ||||
|             height: 300, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar7.png', | ||||
|             dataX: '', | ||||
|             zIndex: 1, | ||||
|             dataY: [], | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23 }, | ||||
|               { name: '水电费', v1: 12 }, | ||||
|               { name: '凡哥', v1: 67 }, | ||||
|               { name: '党费', v1: 98 } | ||||
|             ], | ||||
|             config: barChart7, | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'barChart8', | ||||
|             label: '柱状图6', | ||||
|             title: '柱状图6', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             width: 500, | ||||
|             sourceDataId: '', | ||||
|             border: 'border1', | ||||
|             height: 300, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar8.png', | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             zIndex: 1, | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23 }, | ||||
|               { name: '水电费', v1: 12 }, | ||||
|               { name: '凡哥', v1: 67 }, | ||||
|               { name: '党费', v1: 98 } | ||||
|             ], | ||||
|             config: barChart8, | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'barChart9', | ||||
|             label: '柱状图7', | ||||
|             title: '柱状图7', | ||||
|             border: 'border1', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             width: 500, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar9.png', | ||||
|             sourceDataId: '', | ||||
|             height: 300, | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             zIndex: 1, | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23 }, | ||||
|               { name: '水电费', v1: 12 }, | ||||
|               { name: '凡哥', v1: 67 }, | ||||
|               { name: '党费', v1: 98 } | ||||
|             ], | ||||
|             config: barChart9, | ||||
|             dynamicData: [] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         label: '折线图', | ||||
|         type: 'line', | ||||
|         list: [ | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'lineChart1', | ||||
|             label: '折线图1', | ||||
|             title: '折线图1', | ||||
|             border: 'border1', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             width: 500, | ||||
|             height: 300, | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             zIndex: 1, | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line1.png', | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23, v2: 33 }, | ||||
|               { name: '水电费', v1: 12, v2: 34 }, | ||||
|               { name: '凡哥', v1: 67, v2: 25 }, | ||||
|               { name: '党费', v1: 98, v2: 85 } | ||||
|             ], | ||||
|             config: lineChart1, | ||||
|             sourceDataId: '', | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'lineChart2', | ||||
|             label: '折线图2', | ||||
|             title: '折线图2', | ||||
|             border: 'border1', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             width: 500, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line2.png', | ||||
|             height: 300, | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             zIndex: 1, | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23, v2: 33 }, | ||||
|               { name: '水电费', v1: 12, v2: 34 }, | ||||
|               { name: '凡哥', v1: 67, v2: 25 }, | ||||
|               { name: '党费', v1: 98, v2: 85 } | ||||
|             ], | ||||
|             config: lineChart2, | ||||
|             sourceDataId: '', | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'lineChart3', | ||||
|             label: '折线图3', | ||||
|             title: '折线图3', | ||||
|             icon: 'icontext_box', | ||||
|             border: 'border1', | ||||
|             value: '', | ||||
|             width: 500, | ||||
|             height: 300, | ||||
|             zIndex: 1, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line3.png', | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23, v2: 33 }, | ||||
|               { name: '水电费', v1: 12, v2: 34 }, | ||||
|               { name: '凡哥', v1: 67, v2: 25 }, | ||||
|               { name: '党费', v1: 98, v2: 85 } | ||||
|             ], | ||||
|             config: lineChart3, | ||||
|             sourceDataId: '', | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'lineChart4', | ||||
|             label: '折线图4', | ||||
|             title: '折线图4', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             border: 'border1', | ||||
|             width: 500, | ||||
|             height: 300, | ||||
|             zIndex: 1, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line4.png', | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23, v2: 33 }, | ||||
|               { name: '水电费', v1: 12, v2: 34 }, | ||||
|               { name: '凡哥', v1: 67, v2: 25 }, | ||||
|               { name: '党费', v1: 98, v2: 85 } | ||||
|             ], | ||||
|             config: lineChart4, | ||||
|             sourceDataId: '', | ||||
|             dynamicData: [] | ||||
|           }, | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'lineChart5', | ||||
|             label: '折线图5', | ||||
|             title: '折线图5', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             border: 'border1', | ||||
|             width: 500, | ||||
|             height: 300, | ||||
|             zIndex: 1, | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             dataX: '', | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line5.png', | ||||
|             dataY: [], | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23, v2: 33 }, | ||||
|               { name: '水电费', v1: 12, v2: 34 }, | ||||
|               { name: '凡哥', v1: 67, v2: 25 }, | ||||
|               { name: '党费', v1: 98, v2: 85 } | ||||
|             ], | ||||
|             config: lineChart5, | ||||
|             sourceDataId: '', | ||||
|             dynamicData: [] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         label: '饼图', | ||||
|         type: 'pie', | ||||
|         list: [ | ||||
|           { | ||||
|             code: 'widget-linechart', | ||||
|             type: 'pieChart', | ||||
|             label: '饼图', | ||||
|             title: '饼图', | ||||
|             icon: 'icontext_box', | ||||
|             value: '', | ||||
|             border: 'border1', | ||||
|             width: 500, | ||||
|             height: 300, | ||||
|             zIndex: 1, | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/pie.png', | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { name: '阿斯达', v1: 23, v2: 33 }, | ||||
|               { name: '水电费', v1: 12, v2: 34 }, | ||||
|               { name: '凡哥', v1: 67, v2: 25 }, | ||||
|               { name: '党费', v1: 98, v2: 85 } | ||||
|             ], | ||||
|             config: pieChart, | ||||
|             sourceDataId: '', | ||||
|             dynamicData: [] | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     type: 'table', | ||||
|     label: '表格', | ||||
|     list: [ | ||||
|       { | ||||
|         label: '表格', | ||||
|         type: 'table', | ||||
|         list: [ | ||||
|           { | ||||
|             type: 'table', | ||||
|             label: '表格', | ||||
|             title: '表格', | ||||
|             border: 'border1', | ||||
|             width: 650, | ||||
|             height: 400, | ||||
|             zIndex: 1, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/table.png', | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             rowNum: 7, | ||||
|             isShowIndex: '1', | ||||
|             sourceDataId: '', | ||||
|             api: '', | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             dynamicData: [], | ||||
|             staticData: [ | ||||
|               { name: '列1', v: 23, v2: 3 }, | ||||
|               { name: '列2', v: 12, v2: 4 }, | ||||
|               { name: '列2', v: 12, v2: 4 } | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     type: 'other', | ||||
|     label: '其他', | ||||
|     list: [ | ||||
|       { | ||||
|         label: '地图', | ||||
|         type: 'map', | ||||
|         list: [ | ||||
|           { | ||||
|             type: 'map', | ||||
|             label: '地图', | ||||
|             display: 'map', | ||||
|             width: 840, | ||||
|             height: 534, | ||||
|             left: 0, | ||||
|             top: 0, | ||||
|             mask: '2', | ||||
|             areaId: '', | ||||
|             zIndex: 1, | ||||
|             apiData: [], | ||||
|             dataType: 'staticData', | ||||
|             dynamicData: [], | ||||
|             staticData: [ | ||||
|               { | ||||
|                 content: '中卫慧通', | ||||
|                 lng: 117.1339399, | ||||
|                 lat: 36.7190487 | ||||
|               } | ||||
|             ], | ||||
|             api: '', | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/map.png' | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         label: '边框', | ||||
|         type: 'panel', | ||||
|         list: [ | ||||
|           { | ||||
|             type: 'panel', | ||||
|             label: '边框', | ||||
|             title: '边框', | ||||
|             border: 'border0', | ||||
|             width: 400, | ||||
|             height: 400, | ||||
|             isZoom: false, | ||||
|             zIndex: 1, | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/border.png' | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         label: '装饰', | ||||
|         type: 'display', | ||||
|         list: [ | ||||
|           { | ||||
|             type: 'display', | ||||
|             label: '装饰', | ||||
|             display: 'display0', | ||||
|             width: 840, | ||||
|             height: 540, | ||||
|             isZoom: false, | ||||
|             zIndex: 1, | ||||
|             title: '标题', | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/display.png', | ||||
|             sourceDataId: '', | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { | ||||
|                 key: '个人服务办理', | ||||
|                 value: 247 | ||||
|               }, | ||||
|               { | ||||
|                 key: '同比上月', | ||||
|                 value: 247 | ||||
|               } | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         label: '轮播图', | ||||
|         type: 'swiper', | ||||
|         list: [ | ||||
|           { | ||||
|             type: 'swiper', | ||||
|             label: '轮播图', | ||||
|             width: 400, | ||||
|             height: 300, | ||||
|             zIndex: 1, | ||||
|             border: 'border2', | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { | ||||
|                 img: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/pie.png', | ||||
|                 title: '湖羊', | ||||
|                 content: `歙县众城湖羊养殖专业合作社 | ||||
| 							徐晓红 - 18273645627 | ||||
| 							歙县郑村镇唐跃村碉墅` | ||||
|               } | ||||
|             ], | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/swiper.png' | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         label: '视频播放器', | ||||
|         type: 'video', | ||||
|         list: [ | ||||
|           { | ||||
|             type: 'video', | ||||
|             label: '视频播放器', | ||||
|             width: 400, | ||||
|             height: 300, | ||||
|             zIndex: 1, | ||||
|             src: '', | ||||
|             border: 'border2', | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/swiper.png' | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         label: '数据统计', | ||||
|         type: 'summary', | ||||
|         list: [ | ||||
|           { | ||||
|             type: 'summary', | ||||
|             label: '数据统计', | ||||
|             display: 'summary0', | ||||
|             width: 480, | ||||
|             height: 240, | ||||
|             zIndex: 1, | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             dataX: '', | ||||
|             dataY: [], | ||||
|             border: 'border3', | ||||
|             sourceDataId: '', | ||||
|             title: '数据统计', | ||||
|             dataType: 'staticData', | ||||
|             staticData: [ | ||||
|               { | ||||
|                 key: '个人服务办理', | ||||
|                 value: 247 | ||||
|               }, | ||||
|               { | ||||
|                 key: '同比上月', | ||||
|                 value: 247 | ||||
|               } | ||||
|             ], | ||||
|             dynamicData: [], | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/total.png' | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         label: '视频监控', | ||||
|         type: 'monitor', | ||||
|         list: [ | ||||
|           { | ||||
|             type: 'monitor', | ||||
|             label: '视频监控', | ||||
|             src: '', | ||||
|             width: 480, | ||||
|             height: 240, | ||||
|             zIndex: 1, | ||||
|             top: 0, | ||||
|             left: 0, | ||||
|             title: '', | ||||
|             moniterId: '', | ||||
|             monitorType: 'cmcc', | ||||
|             api: '/app/appzyvideoequipment/list', | ||||
|             border: 'border2', | ||||
|             sourceDataId: '', | ||||
|             dataType: 'staticData', | ||||
|             staticData: '', | ||||
|             dynamicData: '', | ||||
|             thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/video.png' | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| ] | ||||
|  | ||||
| export { components } | ||||
							
								
								
									
										88
									
								
								packages/bigscreen/ui/AiDataPanel.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								packages/bigscreen/ui/AiDataPanel.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| <template> | ||||
|   <section class="AiDataPanel"> | ||||
|     <b class="item-title" v-text="label"/> | ||||
|     <div class="num-bg"> | ||||
|       <span ref="num" class="num" v-text="num"/> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {gsap} from 'gsap' | ||||
|  | ||||
| export default { | ||||
|   name: "AiDataPanel", | ||||
|   props: { | ||||
|     label: {default: "标题"}, | ||||
|     value: {default: 0} | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       num: 0 | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     animation() { | ||||
|       let demo = {num: Math.max(this.value - 30, 0)} | ||||
|       gsap.to(demo, 1, { | ||||
|         num: this.value, onUpdate: () => { | ||||
|           this.num = demo.num?.toFixed(0) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.animation() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AiDataPanel { | ||||
|   flex: 1; | ||||
|   width: 172px; | ||||
|   height: 160px; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   align-items: center; | ||||
|   background: #000; | ||||
|  | ||||
|   & + .AiDataPanel { | ||||
|     margin-left: 16px; | ||||
|   } | ||||
|  | ||||
|   .item-title { | ||||
|     font-size: 24px; | ||||
|     line-height: 32px; | ||||
|     background-image: -webkit-linear-gradient(bottom, #35BEFF, #EBF9FF, #FFFFFF); | ||||
|     -webkit-background-clip: text; | ||||
|     -webkit-text-fill-color: transparent; | ||||
|     margin-top: 30px; | ||||
|   } | ||||
|  | ||||
|   .num-bg { | ||||
|     width: 100%; | ||||
|     height: 160px; | ||||
|     background-image: url(https://cdn.cunwuyun.cn/dvcp/dv/dianjiang/number-bg.png); | ||||
|     background-size: 100% 100%; | ||||
|     position: relative; | ||||
|     margin-top: -76px; | ||||
|  | ||||
|     .num { | ||||
|       position: absolute; | ||||
|       left: 0; | ||||
|       bottom: 30px; | ||||
|       width: 100%; | ||||
|       text-align: center; | ||||
|       height: 50px; | ||||
|       font-size: 40px; | ||||
|       font-family: D-DIN-Bold, D-DIN; | ||||
|       font-weight: bold; | ||||
|       line-height: 54px; | ||||
|       background-image: -webkit-linear-gradient(bottom, #35BEFF, #EBF9FF, #FFFFFF); | ||||
|       -webkit-background-clip: text; | ||||
|       -webkit-text-fill-color: transparent; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										30
									
								
								packages/bigscreen/ui/AiStaData.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								packages/bigscreen/ui/AiStaData.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| <template> | ||||
|   <section class="AiStaData"> | ||||
|     <ai-data-panel v-for="op in data" :key="op[key]" | ||||
|                    :label="op[label]" :value="op[key]"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AiDataPanel from "./AiDataPanel"; | ||||
|  | ||||
| export default { | ||||
|   name: "AiStaData", | ||||
|   components: {AiDataPanel}, | ||||
|   props: { | ||||
|     data: {default: () => []}, | ||||
|     key: {default: "id"}, | ||||
|     label: {default: "label"}, | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AiStaData { | ||||
|   width: 100%; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   flex-wrap: wrap; | ||||
|   justify-content: center; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										181
									
								
								packages/bigscreen/viewer/AppGigscreenViewer.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								packages/bigscreen/viewer/AppGigscreenViewer.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,181 @@ | ||||
| <template> | ||||
|   <div class="AppGigscreenViewer"> | ||||
|     <div v-if="!component"> | ||||
|       <div | ||||
|         :style="{ | ||||
|           width: item.width + 'px', | ||||
|           height: item.height + 'px', | ||||
|           left: item.left + 'px', | ||||
|           top: item.top + 'px', | ||||
|           position: 'absolute', | ||||
|           zIndex: item.zIndex | ||||
|         }" | ||||
|         v-for="(item, index) in componentList" | ||||
|         :key="index"> | ||||
|         <RenderElement :data="item" :index="index"></RenderElement> | ||||
|       </div> | ||||
|     </div> | ||||
|     <components v-else :is="component" :dict="dict" :instance="instance" :nav="meta"/> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import RenderElement from '../designer/components/RenderElement' | ||||
|  | ||||
|   export default { | ||||
|     name: 'AppGigscreenViewer', | ||||
|     label: '大屏预览', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       id: String, | ||||
|       urlPrefix: { | ||||
|         type: String, | ||||
|         default: '/app' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     watch: { | ||||
|       id(v) { | ||||
|         this.getInfo(v) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       RenderElement | ||||
|     }, | ||||
|  | ||||
|     data() { | ||||
|       return { | ||||
|         component: '', | ||||
|         dashboard: { | ||||
|           title: '大屏', | ||||
|           width: 1920, | ||||
|           height: 1080, | ||||
|           backgroundColor: '', | ||||
|           backgroundImage: [] | ||||
|         }, | ||||
|         componentList: [], | ||||
|         meta: {} | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created() { | ||||
|       this.getInfo(this.id) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getInfo(id) { | ||||
|         this.component = null | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenDetailById?id=${id}`).then(res => { | ||||
|           if (res?.data) { | ||||
|             const config = JSON.parse(res.data.config) | ||||
|             if (config.custom) { | ||||
|               this.component = config.custom | ||||
|               this.meta = config?.meta || {} | ||||
|             } else { | ||||
|               this.componentList = JSON.parse(res.data.config).config | ||||
|               this.dashboard = JSON.parse(res.data.config).dashboard | ||||
|  | ||||
|               this.componentList.forEach((item, index) => { | ||||
|                 if (item.dataType !== 'staticData' && ((item.type.indexOf('Chart') > -1) || item.type === 'table' || item.type === 'summary')) { | ||||
|                   this.getSourceData(item, index) | ||||
|                 } | ||||
|                 if (item.type === 'monitor' && item.monitorType !== 'hik') { | ||||
|                   this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${item.moniterId}`).then(res => { | ||||
|                     if (res.code == 0) { | ||||
|                       this.$set(this.componentList[index], 'src', JSON.parse(res.data).url) | ||||
|                     } | ||||
|                   }) | ||||
|                 } | ||||
|               }) | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getSourceData(item, index) { | ||||
|         const api = item.dataType === 'apiData' ? item.api : `${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${item.sourceDataId}` | ||||
|         this.instance.post(api).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             if (res.data.length) { | ||||
|               const keys = Object.keys(res.data[0]) | ||||
|               const list = res.data | ||||
|               let dynamicData = [] | ||||
|               if (item.type === 'table') { | ||||
|                 dynamicData = keys.map(v => { | ||||
|                   let obj = {} | ||||
|                   list.forEach((item, index) => { | ||||
|                     obj[`v${index}`] = item[v] | ||||
|                   }) | ||||
|  | ||||
|                   return { | ||||
|                     row: v, | ||||
|                     ...obj | ||||
|                   } | ||||
|                 }) | ||||
|               } else if (item.type === 'summary') { | ||||
|                 dynamicData = Object.keys(res.data[0]).map(item => { | ||||
|                   return { | ||||
|                     key: item, | ||||
|                     value: res.data[0][item] | ||||
|                   } | ||||
|                 }) | ||||
|               } else { | ||||
|                 if (item.dataX && item.dataY.length) { | ||||
|                   list.forEach(i => { | ||||
|                     let obj = {} | ||||
|                     item.dataY.forEach(v => { | ||||
|                       obj[v] = i[v] | ||||
|                     }) | ||||
|                     dynamicData.push({ | ||||
|                       [item.dataX]: i[item.dataX], | ||||
|                       ...obj | ||||
|                     }) | ||||
|                   }) | ||||
|                 } | ||||
|               } | ||||
|  | ||||
|               this.$set(this.componentList[index], item.dataType, dynamicData) | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       close() { | ||||
|         this.$emit('close') | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppGigscreenViewer { | ||||
|   position: relative; | ||||
|   height: 100%; | ||||
|   background: transparent !important; | ||||
|  | ||||
|   .dv-scroll-board { | ||||
|     height: calc(100%) !important; | ||||
|  | ||||
|     .header-item { | ||||
|       color: #7e8697; | ||||
|       font-size: 16px; | ||||
|     } | ||||
|  | ||||
|     .index { | ||||
|       display: inline-block; | ||||
|       width: 26px; | ||||
|       height: 26px; | ||||
|       line-height: 26px; | ||||
|       font-size: 16px; | ||||
|       background-color: #4F57FF !important; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .vdr { | ||||
|     border: none; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user