构建版本修改
This commit is contained in:
		
							
								
								
									
										288
									
								
								packages/core/AppAccount/AppAccount.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								packages/core/AppAccount/AppAccount.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,288 @@ | ||||
| <template> | ||||
|   <section class="AppAccount"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="账号管理" isShowBottomBorder> | ||||
|         <template #rightBtn> | ||||
|           <el-button size="small" type="primary" icon="iconfont iconUpdate_Files" @click="syncDept">同步部门</el-button> | ||||
|         </template> | ||||
|       </ai-title> | ||||
|       <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> | ||||
|             <el-button size="small" icon="iconfont iconUpdate_Files" @click="syncMembers">同步成员</el-button> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input size="small" placeholder="搜索姓名、手机号" v-model="search.name" clearable | ||||
|                       v-throttle="() => {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: "账号管理(村微版)", | ||||
|   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: [], | ||||
|       lock: false | ||||
|     } | ||||
|   }, | ||||
|   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) { | ||||
|           if (this.lock) return this.$message.error("请勿多次提交!") | ||||
|           this.lock = true | ||||
|           this.instance.post("/app/wxcp/wxuser/empower", this.dialogForm).then(res => { | ||||
|             this.lock = false | ||||
|             if (res?.code == 0) { | ||||
|               this.dialog = false; | ||||
|               this.$message.success("修改成功") | ||||
|               this.getTableData(); | ||||
|             } else { | ||||
|               this.$message.error(res?.msg) | ||||
|             } | ||||
|           }).catch(() => { | ||||
|             this.lock = false | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     syncMembers() { | ||||
|       const {departmentId = 1} = this.search; | ||||
|       let loading = this.$loading({ | ||||
|         text: "正在同步成员...", | ||||
|         spinner: 'el-icon-loading', | ||||
|         background: "rgba(0,0,0,.8)" | ||||
|       }) | ||||
|       this.instance.post(`/app/wxcp/wxdepartment/syncUser`, null, { | ||||
|         timeout: 1000000, | ||||
|         params: {departmentId} | ||||
|       }).then(res => { | ||||
|         if (res?.code == 0) { | ||||
|           this.$message.success('同步成功') | ||||
|           this.getList() | ||||
|         } | ||||
|       }).finally(() => loading.close()) | ||||
|     }, | ||||
|     syncDept() { | ||||
|       let loading = this.$loading({ | ||||
|         text: "正在同步部门...", | ||||
|         spinner: 'el-icon-loading', | ||||
|         background: "rgba(0,0,0,.8)" | ||||
|       }) | ||||
|       this.instance.post(`/app/wxcp/wxdepartment/syncDepart`).then(res => { | ||||
|         if (res?.code == 0) { | ||||
|           this.$message.success('同步成功') | ||||
|           this.getTree() | ||||
|         } | ||||
|       }).finally(() => loading.close()) | ||||
|     } | ||||
|   }, | ||||
|   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> | ||||
							
								
								
									
										35
									
								
								packages/core/AppAccountRole/AppAccountRole.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								packages/core/AppAccountRole/AppAccountRole.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <template> | ||||
|   <section class="AppAccountRole"> | ||||
|     <add-account-role v-if="showDetail"/> | ||||
|     <account-role-list v-else/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AddAccountRole from "./addAccountRole"; | ||||
| import AccountRoleList from "./accountRoleList"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppAccountRole", | ||||
|   label: "账号角色管理", | ||||
|   props: { | ||||
|     instance: Function | ||||
|   }, | ||||
|   components: {AccountRoleList, AddAccountRole}, | ||||
|   computed: { | ||||
|     showDetail() { | ||||
|       return this.$route.hash == "#add" | ||||
|     } | ||||
|   }, | ||||
|   provide() { | ||||
|     let {instance} = this | ||||
|     return {instance} | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppAccountRole { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										372
									
								
								packages/core/AppAccountRole/accountRoleList.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										372
									
								
								packages/core/AppAccountRole/accountRoleList.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,372 @@ | ||||
| <template> | ||||
|   <ai-list class="accountRoleList"> | ||||
|     <ai-title slot="title" title="账号角色管理" isShowBottomBorder/> | ||||
|     <template #content> | ||||
|       <ai-search-bar> | ||||
|         <template #left> | ||||
|           <el-button | ||||
|               type="primary" | ||||
|               icon="el-icon-circle-plus" | ||||
|               @click="$router.push({hash:'#add'})" | ||||
|               v-if="$permissions('admin_sysaccountrole_add')" | ||||
|           >添加 | ||||
|           </el-button> | ||||
|           <el-button | ||||
|               icon="el-icon-delete" | ||||
|               class="delete-btn del-btn-list" | ||||
|               @click="allDelete" | ||||
|               :disabled="!Boolean(multipleSelection.length)" | ||||
|               v-if="$permissions('admin_sysaccountrole_del')" | ||||
|           >删除 | ||||
|           </el-button> | ||||
|         </template> | ||||
|         <template #right> | ||||
|           <el-input | ||||
|               size="small" | ||||
|               v-model="searchInfo" | ||||
|               placeholder="角色名称" | ||||
|               clearable | ||||
|               @keyup.enter.native="mhSearch()" | ||||
|               prefix-icon="iconfont iconSearch" | ||||
|           /> | ||||
|           <el-button | ||||
|               type="primary" | ||||
|               icon="iconfont iconSearch" | ||||
|               @click="mhSearch()" | ||||
|           >查询 | ||||
|           </el-button | ||||
|           > | ||||
|           <el-button | ||||
|               icon="el-icon-refresh-right" | ||||
|               style="padding: 8px 13.5px" | ||||
|               @click="resetConditon" | ||||
|           >重置 | ||||
|           </el-button | ||||
|           > | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <el-table | ||||
|           :data="tableData" | ||||
|           @selection-change="handleSelectionChange" | ||||
|           header-cell-class-name="table-header" | ||||
|           tooltip-effect="light" | ||||
|           max-height="calc(100% - 80px)" | ||||
|           row-class-name="table-row" | ||||
|           cell-class-name="table-cell" | ||||
|       > | ||||
|         <el-table-column type="selection" width="55"/> | ||||
|         <el-table-column prop="name" label="角色名" width="300"/> | ||||
|         <el-table-column label="权限明细" prop="appRoleList"> | ||||
|           <template slot-scope="scope"> | ||||
|             <el-tooltip | ||||
|                 content="更多角色用户请点击详情按钮" | ||||
|                 placement="top" | ||||
|                 effect="light" | ||||
|                 v-if="scope.row.appRoleList.length > 3" | ||||
|             > | ||||
|               <span>{{ scope.row.appRoleListHtml }}</span> | ||||
|             </el-tooltip> | ||||
|             <span | ||||
|                 v-for="(item, index) in scope.row.appRoleList" | ||||
|                 :key="index" | ||||
|                 v-else | ||||
|             > | ||||
|               <span>{{ item.appName }}-</span> | ||||
|               <span>{{ item.name }};</span> | ||||
|             </span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="操作" fixed="right" align="center"> | ||||
|           <template class="operation_icon" slot-scope="scope"> | ||||
|             <el-button | ||||
|                 type="text" | ||||
|                 size="small" | ||||
|                 @click="beforeCopy(scope.row)" | ||||
|                 v-if="$permissions('admin_sysaccountrole_add')" | ||||
|             >复制角色 | ||||
|             </el-button> | ||||
|             <el-button | ||||
|                 type="text" | ||||
|                 size="small" | ||||
|                 @click="detailShow(scope.row)" | ||||
|                 v-if="$permissions('admin_sysaccountrole_detail')" | ||||
|             >详情 | ||||
|             </el-button> | ||||
|             <el-button | ||||
|                 type="text" | ||||
|                 size="small" | ||||
|                 @click="edit(scope.row)" | ||||
|                 v-if="$permissions('admin_sysaccountrole_edit')" | ||||
|             >编辑 | ||||
|             </el-button | ||||
|             > | ||||
|             <el-button | ||||
|                 type="text" | ||||
|                 size="small" | ||||
|                 @click="beforeDelete(scope.row)" | ||||
|                 v-if="$permissions('admin_sysaccountrole_del')" | ||||
|             >删除 | ||||
|             </el-button | ||||
|             > | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <div slot="empty" class="no-data"></div> | ||||
|       </el-table> | ||||
|       <div class="pagination"> | ||||
|         <el-pagination | ||||
|             @size-change="handleSizeChange" | ||||
|             @current-change="handleCurrentChange" | ||||
|             background | ||||
|             :page-size="pageSize" | ||||
|             :page-sizes="[10, 20, 50, 100, 200]" | ||||
|             layout="total,prev, pager, next,sizes, jumper" | ||||
|             :total="total" | ||||
|         /> | ||||
|       </div> | ||||
|       <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="roleName" | ||||
|                 placeholder="请输入..." | ||||
|                 size="small" | ||||
|                 clearable | ||||
|             /> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|         <div slot="footer" style="text-align: center"> | ||||
|           <el-button | ||||
|               style="width: 92px" | ||||
|               size="small" | ||||
|               class="delete-btn" | ||||
|               @click="copyDialog = false" | ||||
|           >取消 | ||||
|           </el-button | ||||
|           > | ||||
|           <el-button | ||||
|               style="width: 92px" | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               @click="copyFn()" | ||||
|               :disabled="!Boolean(roleName)" | ||||
|           >确认 | ||||
|           </el-button> | ||||
|         </div> | ||||
|       </el-dialog> | ||||
|       <ai-dialog title="账号角色详情" :visible.sync="viewShow" customFooter> | ||||
|         <ai-card title="基本信息"> | ||||
|           <template #content> | ||||
|             <ai-wrapper> | ||||
|               <ai-info-item label="账号角色名称" :value="row.name"/> | ||||
|             </ai-wrapper> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <ai-card title="权限信息"> | ||||
|           <template #content> | ||||
|             <div | ||||
|                 class="view_info" | ||||
|                 v-for="(item, index) in row.appRoleList" | ||||
|                 :key="index" | ||||
|             > | ||||
|               <i class="iconfont iconProlife" style="color: #999"/>  | ||||
|               {{ [item.appName, item.name].join(" / ") }} | ||||
|             </div> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <template #footer> | ||||
|           <el-button | ||||
|               type="primary" | ||||
|               @click="edit(row)" | ||||
|               v-if="$permissions('admin_sysaccountrole_edit')" | ||||
|           >编辑角色 | ||||
|           </el-button> | ||||
|         </template> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
| <script> | ||||
| export default { | ||||
|   name: "accountRoleList", | ||||
|   inject:{ | ||||
|     instance:{} | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       searchInfo: "", | ||||
|       pageSize: 10, | ||||
|       tableData: [], | ||||
|       multipleSelection: [], | ||||
|       total: 0, | ||||
|       pageNum: 1, | ||||
|       row: {}, | ||||
|       deleteIds: [], | ||||
|       copyDialog: false, | ||||
|       roleName: "", | ||||
|       viewShow: false, | ||||
|       titleDel: "", | ||||
|       form: {}, | ||||
|     }; | ||||
|   }, | ||||
|   methods: { | ||||
|     getTableList() { | ||||
|       this.tableData = []; | ||||
|       this.instance.post(`/admin/role-acc/page`, null, { | ||||
|         params: { | ||||
|           pageSize: this.pageSize, | ||||
|           pageNum: this.pageNum, | ||||
|           roleName: this.searchInfo, | ||||
|         }, | ||||
|       }).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.tableData = res.data.records; | ||||
|           this.total = res.data.total; | ||||
|           if (this.tableData.length) { | ||||
|             this.tableData.map((item) => { | ||||
|               if (item.appRoleList.length > 3) { | ||||
|                 item.appRoleListHtml = `${item.appRoleList[0].appName}-${item.appRoleList[0].name};${item.appRoleList[1].appName}-${item.appRoleList[1].name};${item.appRoleList[2].appName}-${item.appRoleList[2].name};`; | ||||
|               } | ||||
|             }); | ||||
|           } | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     dataInit() { | ||||
|       this.deleteIds = []; | ||||
|       this.multipleSelection = []; | ||||
|       this.row = {}; | ||||
|     }, | ||||
|     handleSelectionChange(val) { | ||||
|       this.deleteIds = []; | ||||
|       this.multipleSelection = val; | ||||
|       this.multipleSelection.forEach((e) => { | ||||
|         this.deleteIds.push(e.id); | ||||
|       }); | ||||
|     }, | ||||
|     allDelete() { | ||||
|       this.titleDel = "确定要执行删除操作吗?"; | ||||
|       this.deleteRole(); | ||||
|     }, | ||||
|     beforeDelete(row) { | ||||
|       this.deleteIds = []; | ||||
|       this.row = row; | ||||
|       this.titleDel = "确定需要删除该角色吗?"; | ||||
|       this.deleteIds.push(row.id); | ||||
|       this.deleteRole(); | ||||
|     }, | ||||
|  | ||||
|     beforeCopy(row) { | ||||
|       this.row = row; | ||||
|       this.copyDialog = true; | ||||
|     }, | ||||
|     detailShow(row) { | ||||
|       this.row = row; | ||||
|       this.viewShow = true; | ||||
|     }, | ||||
|     edit(row) { | ||||
|       this.$router.push({ | ||||
|         hash: "#add", | ||||
|         query: { | ||||
|           info: row, | ||||
|         }, | ||||
|       }); | ||||
|     }, | ||||
|     copyFn() { | ||||
|       let crr = []; | ||||
|       let appRoleList = this.row.appRoleList; | ||||
|       appRoleList.forEach((e) => { | ||||
|         crr.push(e.id); | ||||
|       }); | ||||
|       this.instance.post(`/admin/role-acc/modify?appRoles=${crr}`, null, { | ||||
|         params: { | ||||
|           roleName: this.roleName, | ||||
|         }, | ||||
|       }) | ||||
|       .then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.$message({message: "复制成功", type: "success"}); | ||||
|           this.copyDialog = false; | ||||
|           this.pageNum = 1; | ||||
|           this.getTableList(); | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     deleteRole() { | ||||
|       this.$confirm(this.titleDel, { | ||||
|         type: "error", | ||||
|       }) | ||||
|       .then(() => { | ||||
|         this.instance | ||||
|         .post(`/admin/role-acc/del?ids=${this.deleteIds}`, null, {}) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success("删掉角色成功"); | ||||
|             this.getTableList(); | ||||
|           } | ||||
|         }); | ||||
|       }) | ||||
|       .catch(() => { | ||||
|       }); | ||||
|     }, | ||||
|     mhSearch() { | ||||
|       this.pageNum = 1; | ||||
|       this.getTableList(); | ||||
|     }, | ||||
|     // 重置 | ||||
|     resetConditon() { | ||||
|       this.pageNum = 1; | ||||
|       this.searchInfo = ""; | ||||
|       this.getTableList(); | ||||
|     }, | ||||
|     handleSizeChange(val) { | ||||
|       this.pageSize = val; | ||||
|       this.getTableList(); | ||||
|     }, | ||||
|     handleCurrentChange(val) { | ||||
|       this.pageNum = val; | ||||
|       this.getTableList(); | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTableList(); | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| .accountRoleList { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep.ai-card { | ||||
|     box-shadow: none; | ||||
|     border: 1px solid #eee; | ||||
|  | ||||
|     .aibar { | ||||
|       height: 40px; | ||||
|       background: #f3f6f9; | ||||
|     } | ||||
|  | ||||
|     .ai-card__body { | ||||
|       padding: 0 16px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .view_info { | ||||
|     color: #333; | ||||
|     padding-left: 20px; | ||||
|     margin-bottom: 10px; | ||||
|  | ||||
|     .info-title { | ||||
|       margin-bottom: 10px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										170
									
								
								packages/core/AppAccountRole/addAccountRole.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								packages/core/AppAccountRole/addAccountRole.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| <template> | ||||
|   <section class="addAccountRole"> | ||||
|     <ai-detail> | ||||
|       <ai-title slot="title" :title="pageTitle" isShowBottomBorder isShowBack @onBackClick="$router.push({})"/> | ||||
|       <template #content> | ||||
|         <ai-card title="基本信息"> | ||||
|           <template #content> | ||||
|             <el-form size="small" label-width="120px"> | ||||
|               <el-form-item required label="账号角色名称"> | ||||
|                 <el-input clearable v-model="roleName" placeholder="请输入..."/> | ||||
|               </el-form-item> | ||||
|             </el-form> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <ai-card title="角色信息(必选)"> | ||||
|           <template #content> | ||||
|             <el-form size="small" label-width="120px"> | ||||
|               <el-form-item required label="角色列表"> | ||||
|                 <div class="roleList"> | ||||
|                   <p class="input"> | ||||
|                     <el-input placeholder="请输入..." size="small" v-model="filterText" suffix-icon="iconfont iconSearch"> | ||||
|                     </el-input> | ||||
|                     <el-button icon="iconfont iconDelete" size="small" @click="filterText=''">清空</el-button> | ||||
|                   </p> | ||||
|                   <div class="tree_list"> | ||||
|                     <el-tree | ||||
|                         class="filter-tree" | ||||
|                         :data="roleList" | ||||
|                         show-checkbox | ||||
|                         :props="defaultProps" | ||||
|                         default-expand-all | ||||
|                         :check-strictly="true" | ||||
|                         node-key="id" | ||||
|                         :default-checked-keys="defaultId" | ||||
|                         :filter-node-method="filterNode" | ||||
|                         ref="tree"> | ||||
|                     </el-tree> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </el-form-item> | ||||
|             </el-form> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </template> | ||||
|       <template #footer> | ||||
|         <el-button @click="toAppRole">取消</el-button> | ||||
|         <el-button type="primary" @click="confirm">保存</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
| <script> | ||||
|  | ||||
| export default { | ||||
|   name: "addAccountRole", | ||||
|   inject: {instance: {}}, | ||||
|   data() { | ||||
|     return { | ||||
|       roleName: '', | ||||
|       id: '', | ||||
|       roleList: [], | ||||
|       searchVal: '', | ||||
|       defaultProps: { | ||||
|         children: 'roles', | ||||
|         label: 'name' | ||||
|       }, | ||||
|       treeList: [], | ||||
|       defaultId: [], | ||||
|       filterText: '' | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     isAdd() { | ||||
|       return !this.$route.query?.info?.id | ||||
|     }, | ||||
|     pageTitle() { | ||||
|       return this.isAdd ? "新增账号角色" : "编辑账号角色" | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     filterText(val) { | ||||
|       this.$refs.tree.filter(val); | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getAppList(); | ||||
|     if (JSON.stringify(this.$route.query) != '{}') { | ||||
|       this.roleName = this.$route.query.info.name; | ||||
|       this.id = this.$route.query.info.id; | ||||
|       this.$route.query.info.appRoleList.forEach(e => { | ||||
|         this.defaultId.push(e.id) | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     //查询下拉列表 | ||||
|     getAppList() { | ||||
|       this.instance.post(`/admin/role-app/list-all`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.roleList = res.data; | ||||
|           this.roleList.forEach(e => { | ||||
|             e.disabled = true; | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     filterNode(value, data) { | ||||
|       if (!value) return true; | ||||
|       return data.name.indexOf(value) !== -1; | ||||
|     }, | ||||
|     confirm() { | ||||
|       let crr = []; | ||||
|       let arrCheckList = []; | ||||
|       arrCheckList = this.$refs.tree.getCheckedKeys(); | ||||
|       for (let i = 0; i < arrCheckList.length; i++) { | ||||
|         crr.push(arrCheckList[i]); | ||||
|       } | ||||
|       if (!this.roleName) { | ||||
|         this.$message.error('请输入账号角色名称') | ||||
|         return; | ||||
|       } | ||||
|       if (crr.length == 0) { | ||||
|         this.$message.error('请选择角色列表') | ||||
|         return; | ||||
|       } | ||||
|       this.instance.post(`/admin/role-acc/modify?appRoles=${crr}`, null, { | ||||
|         params: { | ||||
|           roleName: this.roleName, | ||||
|           id: this.id | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res?.code == 0) { | ||||
|           this.$message({message: '保存成功', type: 'success'}); | ||||
|           this.toAppRole() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     //取消 返回 | ||||
|     toAppRole() { | ||||
|       this.$router.push({}) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| .addAccountRole { | ||||
|   height: 100%; | ||||
|  | ||||
|   .roleList { | ||||
|     display: inline-block; | ||||
|     width: 340px; | ||||
|     height: 420px; | ||||
|     background-color: #fcfcfc; | ||||
|     border-radius: 2px; | ||||
|     border: solid 1px #d0d4dc; | ||||
|  | ||||
|     .input { | ||||
|       display: flex; | ||||
|       justify-content: space-between; | ||||
|       padding: 5px; | ||||
|       margin: 0; | ||||
|     } | ||||
|  | ||||
|     .tree_list { | ||||
|       height: 370px; | ||||
|       overflow: auto; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										156
									
								
								packages/core/AppDictionary/AppDictionary.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								packages/core/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
									
								
								packages/core/AppDictionary/dictDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								packages/core/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> | ||||
							
								
								
									
										35
									
								
								packages/core/AppMenuManager/AppMenuManager.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								packages/core/AppMenuManager/AppMenuManager.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <template> | ||||
|   <section class="AppMenuManager"> | ||||
|     <component :is="currentPage" v-bind="$props"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from "./list"; | ||||
| import IntroPage from "./introPage"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppMenuManager", | ||||
|   components: {IntroPage, List}, | ||||
|   label: "菜单管理", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: {default: () => ({})} | ||||
|   }, | ||||
|   computed: { | ||||
|     currentPage() { | ||||
|       const {hash} = this.$route | ||||
|       return hash == "#intro" ? IntroPage : List | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load("menuType", "yesOrNo") | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppMenuManager { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										96
									
								
								packages/core/AppMenuManager/introPage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								packages/core/AppMenuManager/introPage.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| <template> | ||||
|   <section class="introPage"> | ||||
|     <ai-detail :list="!edit"> | ||||
|       <ai-title slot="title" title="引导页配置" isShowBottomBorder isShowBack @onBackClick="$router.push({})"> | ||||
|         <template #rightBtn> | ||||
|           <ai-edit-btn @edit="edit=true,getConfigs()" @cancel="edit=false" @submit="submit"/> | ||||
|         </template> | ||||
|       </ai-title> | ||||
|       <template #content> | ||||
|         <el-form v-if="edit" :model="form" ref="IntroForm" size="small" :rules="rules" label-width="120px"> | ||||
|           <ai-card title="基本信息"> | ||||
|             <template #content> | ||||
|               <el-form-item label="副标题" prop="subtitle"> | ||||
|                 <el-input v-model="form.subtitle" clearable placeholder="请输入"/> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="操作示例链接" prop="operationExamples"> | ||||
|                 <el-input v-model="form.operationExamples" clearable placeholder="请输入"/> | ||||
|               </el-form-item> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card title="引导内容"> | ||||
|             <template #content> | ||||
|               <el-form-item label-width="0" prop="guideContent"> | ||||
|                 <ai-editor :instance="instance" v-model="form.guideContent" placeholder="请输入" action="/oms/api/file/add" :params="{withoutToken:true}"/> | ||||
|               </el-form-item> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|         </el-form> | ||||
|         <ai-intro v-else :id="$route.query.id" v-bind="$props"/> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|  | ||||
| import AiEditBtn from "../../../components/AiEditBtn"; | ||||
| export default { | ||||
|   name: "introPage", | ||||
|   components: {AiEditBtn}, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: {default: () => ({})} | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       form: {}, | ||||
|       rules: { | ||||
|         subtitle: {required: true, message: "请输入副标题"}, | ||||
|         guideContent: {required: true, message: "请输入引导内容"}, | ||||
|       }, | ||||
|       edit: false | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getConfigs() { | ||||
|       const {id} = this.$route.query | ||||
|       this.instance.post("/admin/sysappguideconfig/queryDetailById", null, { | ||||
|         params: {id} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.form = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     submit(cb) { | ||||
|       this.$refs.IntroForm.validate(v => { | ||||
|         if (v) { | ||||
|           const {form, $route: {query: {id}}} = this | ||||
|           this.instance.post("/admin/sysappguideconfig/addOrUpdate", {...form, id}).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success("提交成功!") | ||||
|               cb() | ||||
|               this.edit = false | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .introPage { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep.ai-detail__content--wrapper { | ||||
|     min-height: 100%; | ||||
|  | ||||
|     &.list { | ||||
|       padding-top: 0; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										268
									
								
								packages/core/AppMenuManager/list.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								packages/core/AppMenuManager/list.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,268 @@ | ||||
| <template> | ||||
|   <section class="list"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="菜单配置" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <el-button type="primary" icon="el-icon-circle-plus" @click="addRootMenu">添加一级目录</el-button> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input size="small" v-model="search" clearable @change="$refs.MenuTree.filter(search)" | ||||
|                       placeholder="菜单名称"/> | ||||
|             <el-button icon="iconfont iconResetting" @click="getData">刷新</el-button> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <el-row type="flex" class="headerRow"> | ||||
|           <div class="menuName" v-text="`菜单名称`"/> | ||||
|           <el-row type="flex" align="middle" class="info"> | ||||
|             <div class="style" v-text="`图标`"/> | ||||
|             <div class="type" v-text="`菜单类型`"/> | ||||
|             <div class="component" v-text="`应用模块`"/> | ||||
|             <div class="status" v-text="`是否显示`"/> | ||||
|             <div class="showIndex" v-text="`排序`"/> | ||||
|           </el-row> | ||||
|           <div class="operation" v-text="`操作`"/> | ||||
|         </el-row> | ||||
|         <el-scrollbar> | ||||
|           <el-tree ref="MenuTree" :data="treeData" :props="{children:'subSet'}" highlight-current node-key="id" | ||||
|                    :filter-node-method="handleSearch"> | ||||
|             <el-row type="flex" align="middle" slot-scope="{node,data}" class="menuItem"> | ||||
|               <div class="menuName" v-text="data.name"/> | ||||
|               <el-row type="flex" align="middle" class="info"> | ||||
|                 <div class="style" :class="data.style"/> | ||||
|                 <div class="type" v-text="dict.getLabel('menuType',data.type)"/> | ||||
|                 <div class="component" v-text="data.component"/> | ||||
|                 <div class="status" v-text="dict.getLabel('yesOrNo',data.status)"/> | ||||
|                 <div class="showIndex" v-text="data.showIndex"/> | ||||
|               </el-row> | ||||
|               <el-row type="flex" align="middle" class="operation"> | ||||
|                 <div v-if="node.isLeaf" class="opBtn del" v-text="`删除`" @click="handleDelete(data)"/> | ||||
|                 <div v-if="data.component&&data.type==1" class="opBtn" v-text="`引导页`" @click="$router.push({hash:'#intro',query:{id:data.id}})"/> | ||||
|                 <div v-if="data.type<2" class="opBtn" v-text="`添加下级`" @click="addMenu(data)"/> | ||||
|                 <div class="opBtn" v-text="`编辑`" @click="handleEdit(data)"/> | ||||
|               </el-row> | ||||
|             </el-row> | ||||
|           </el-tree> | ||||
|         </el-scrollbar> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <ai-dialog :visible.sync="dialog" title="菜单设置" width="500px" @onConfirm="handleSubmit" | ||||
|                @closed="form={},selected={}"> | ||||
|       <el-form ref="MenuForm" :model="form" size="small" label-width="100px" :rules="rules"> | ||||
|         <el-form-item label="菜单名称" prop="name"> | ||||
|           <el-input v-model="form.name" placeholder="请输入" clearable/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="菜单类型" prop="type"> | ||||
|           <ai-select v-model="form.type" clearable :selectList="dict.getDict('menuType')"/> | ||||
|         </el-form-item> | ||||
|         <template v-if="form.type==0"> | ||||
|           <el-form-item label="菜单图标" prop="style"> | ||||
|             <el-input v-model="form.style" placeholder="请输入" clearable/> | ||||
|           </el-form-item> | ||||
|         </template> | ||||
|         <template v-if="form.type==1"> | ||||
|           <el-form-item label="路由名" prop="route"> | ||||
|             <span v-text="form.route||'提交保存后会自动生成'"/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="菜单应用" prop="component"> | ||||
|             <el-input v-model="form.component" placeholder="请输入" clearable/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="路径(path)" prop="path"> | ||||
|             <el-input v-model="form.path" placeholder="请输入" clearable/> | ||||
|           </el-form-item> | ||||
|         </template> | ||||
|         <template v-if="form.type==2"> | ||||
|           <el-form-item label="权限码" prop="permission"> | ||||
|             <el-input v-model="form.permission" placeholder="请输入" clearable/> | ||||
|           </el-form-item> | ||||
|         </template> | ||||
|         <el-form-item label="显示菜单" prop="status"> | ||||
|           <ai-select v-model="form.status" clearable :selectList="dict.getDict('yesOrNo')"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item v-if="form.type<2" label="排序" prop="showIndex"> | ||||
|           <el-input v-model="form.showIndex" placeholder="请输入" clearable/> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|  | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "list", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: {default: () => ({})} | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       treeData: [], | ||||
|       dialog: false, | ||||
|       form: {}, | ||||
|       selected: {}, | ||||
|       rules: { | ||||
|         name: [{required: true, message: "请输入 菜单名称"}], | ||||
|         type: [{required: true, message: "请选择 菜单类型"}], | ||||
|         status: [{required: true, message: "请选择 显示菜单"}], | ||||
|         showIndex: [{required: true, message: "请输入 排序"}], | ||||
|         permission: [{required: true, message: "请输入 权限码"}], | ||||
|       }, | ||||
|       search: "" | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getData() { | ||||
|       return this.instance.post("/admin/menu/menuTree").then(res => { | ||||
|         if (res?.data) { | ||||
|           this.treeData = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleSubmit() { | ||||
|       this.$refs.MenuForm.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post("/admin/menu/addOrUpdate", this.form).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success("提交成功!") | ||||
|               this.dialog = false | ||||
|               if (!!this.form.id) { | ||||
|                 let node = this.$refs.MenuTree.getNode(this.form) | ||||
|                 node.data = this.form | ||||
|               } else if (!!this.form.parentId) { | ||||
|                 this.$refs.MenuTree.append(this.form, this.selected) | ||||
|               } else this.getData() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleDelete(data) { | ||||
|       let {id} = data | ||||
|       this.$confirm("是否要删除该菜单").then(() => { | ||||
|         this.instance.post("/admin/menu/delete", null, { | ||||
|           params: {id} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("删除成功!") | ||||
|             this.dialog = false | ||||
|             this.$refs.MenuTree.remove(data) | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     addRootMenu(row) { | ||||
|       this.dialog = true | ||||
|       this.selected = row | ||||
|     }, | ||||
|     addMenu(row) { | ||||
|       this.dialog = true | ||||
|       this.form = {parentId: row.id} | ||||
|       this.selected = row | ||||
|     }, | ||||
|     handleEdit(row) { | ||||
|       this.dialog = true | ||||
|       this.form = JSON.parse(JSON.stringify(row)) | ||||
|       this.selected = row | ||||
|     }, | ||||
|     handleSearch(value, data) { | ||||
|       if (!value) return true; | ||||
|       return data.name.indexOf(value) !== -1; | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getData() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .list { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .ai-list__content--right-wrapper { | ||||
|     height: calc(100% - 10px); | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|  | ||||
|     .el-tree { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|       font-size: 14px; | ||||
|  | ||||
|       .menuItem { | ||||
|         flex: 1; | ||||
|         min-width: 0; | ||||
|       } | ||||
|  | ||||
|       .el-tree-node:nth-of-type(2n) { | ||||
|         background: rgba(#26f, .05); | ||||
|       } | ||||
|  | ||||
|       .el-tree-node__content { | ||||
|         border-bottom: 1px solid #d0d4dc; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .el-scrollbar { | ||||
|       flex: 1; | ||||
|       min-height: 0; | ||||
|  | ||||
|       .el-scrollbar__wrap { | ||||
|         overflow-x: auto; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     .headerRow { | ||||
|       background: #f3f4f5; | ||||
|       color: #666; | ||||
|       font-weight: bold; | ||||
|       align-items: center; | ||||
|       height: 40px; | ||||
|  | ||||
|       .menuName { | ||||
|         padding-left: 16px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .info { | ||||
|       gap: 16px; | ||||
|       text-align: center; | ||||
|  | ||||
|       .showIndex, .status, .type, .style { | ||||
|         width: 80px; | ||||
|       } | ||||
|  | ||||
|       .component { | ||||
|         width: 300px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .operation { | ||||
|       width: 300px; | ||||
|       flex-shrink: 0; | ||||
|       justify-content: flex-end; | ||||
|       text-align: center; | ||||
|  | ||||
|       .opBtn { | ||||
|         cursor: pointer; | ||||
|         width: 60px; | ||||
|  | ||||
|         font-size: 14px; | ||||
|         color: #26f; | ||||
|  | ||||
|         &.del { | ||||
|           color: #f46; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .menuName { | ||||
|       flex: 1; | ||||
|       min-width: 0; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										36
									
								
								packages/core/AppQyWxConfig/AppQyWxConfig.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								packages/core/AppQyWxConfig/AppQyWxConfig.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| <template> | ||||
|   <section class="AppQyWxConfig"> | ||||
|     <component :is="currentPage" v-bind="$props"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from "./list"; | ||||
| import ThemeSetting from "./themeSetting"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppQyWxConfig", | ||||
|   components: {ThemeSetting, List}, | ||||
|   label: "企业微信配置", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     currentPage() { | ||||
|       const {hash} = this.$route | ||||
|       return hash == "#theme" ? ThemeSetting : List | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load("yesOrNo", "themeWeb", 'themeMp', "themeWxwork") | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppQyWxConfig { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										74
									
								
								packages/core/AppQyWxConfig/components/AiSelectCard.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								packages/core/AppQyWxConfig/components/AiSelectCard.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| <template> | ||||
|   <section class="AiSelectCard" flex> | ||||
|     <div class="checkCard" v-for="op in list" :key="op[props.value]" :class="{checked:op.dictValue==value}"> | ||||
|       <el-image :src="op.thumb"/> | ||||
|       <el-row type="flex" class="bottomPane"> | ||||
|         <b class="label fill" v-text="op[props.label]"/> | ||||
|         <el-button type="text" @click.stop="$emit('change',op[props.value])">使用</el-button> | ||||
|       </el-row> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "AiSelectCard", | ||||
|   model: { | ||||
|     prop: "value", | ||||
|     event: "change" | ||||
|   }, | ||||
|   props: { | ||||
|     value: {default: ""}, | ||||
|     ops: {default: () => []}, | ||||
|     type: {default: "web"}, | ||||
|     dict: String, | ||||
|     prop: {default: () => ({})} | ||||
|   }, | ||||
|   computed: { | ||||
|     list: v => (v.dict ? v.$dict.getDict(v.dict) : v.ops || []).map(e => ({ | ||||
|       ...e, | ||||
|       thumb: `https://cdn.cunwuyun.cn/theme/thumb/${v.type}_${e[v.props.value]}.png` | ||||
|     })), | ||||
|     props: v => ({value: 'dictValue', label: 'dictName', ...v.prop}) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AiSelectCard { | ||||
|   display: flex; | ||||
|   flex-wrap: wrap; | ||||
|   gap: 16px; | ||||
|  | ||||
|   .checkCard { | ||||
|     width: 360px; | ||||
|     background: #fff; | ||||
|     border-radius: 8px; | ||||
|     overflow: hidden; | ||||
|     position: relative; | ||||
|  | ||||
|     .label { | ||||
|       user-select: none; | ||||
|     } | ||||
|  | ||||
|     &.checked:before { | ||||
|       position: absolute; | ||||
|       content: "应用中"; | ||||
|       top: 16px; | ||||
|       left: 16px; | ||||
|       z-index: 9; | ||||
|       padding: 8px 16px; | ||||
|       background: rgba(#000, .7); | ||||
|       color: #fff; | ||||
|       border-radius: 8px; | ||||
|     } | ||||
|  | ||||
|     .bottomPane { | ||||
|       height: 48px; | ||||
|       align-items: center; | ||||
|       padding: 0 16px; | ||||
|       border-top: 1px solid #eee; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										481
									
								
								packages/core/AppQyWxConfig/list.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										481
									
								
								packages/core/AppQyWxConfig/list.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,481 @@ | ||||
| <template> | ||||
|   <section class="list"> | ||||
|     <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 | ||||
|                       @clear="page.current = 1,search.name = '', getTableData()" | ||||
|                       v-throttle="() => {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 type="expand" slot="expand"> | ||||
|             <template slot-scope="{row}"> | ||||
|               <ai-wrapper> | ||||
|                 <ai-info-item labelWidth="200px" v-for="op in desConfigs" :key="op.prop" :value="row[op.prop]" | ||||
|                               v-bind="op"/> | ||||
|               </ai-wrapper> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|           <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="miniappStatus" align="center" label="小程序状态" width="150"> | ||||
|             <template v-slot="{ row }"> | ||||
|               <el-switch v-model="row.miniappStatus" @change="onMiniappStatusChange(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="操作" width="400"> | ||||
|             <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-button type="text" @click="handleSystemInfo(row.id)">系统信息</el-button> | ||||
|               <el-button type="text" @click="handlePush(row.id)">推送随手拍样式</el-button> | ||||
|               <el-button type="text" @click="handleTheme(row.id)">主题样式</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="100"></el-input> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="随手拍AGENTID" prop="clapAgentId"> | ||||
|           <el-input v-model.trim="dialogForm.clapAgentId" placeholder="请输入随手拍AGENTID" show-word-limit | ||||
|                     maxlength="100"></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="255"></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="web访问域名" prop="webUrl"> | ||||
|           <el-input v-model.trim="dialogForm.webUrl" placeholder="请输入web访问域名" 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-item label="小程序状态" prop="miniappStatus"> | ||||
|           <el-radio-group v-model.trim="dialogForm.miniappStatus"> | ||||
|             <el-radio label="1">启用</el-radio> | ||||
|             <el-radio label="0">禁用</el-radio> | ||||
|           </el-radio-group> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="系统配置信息" prop="systemInfo"> | ||||
|           <el-input type="textarea" :rows="2" placeholder="请输入系统配置信息" v-model="dialogForm.systemInfo" | ||||
|                     maxlength="50000"/> | ||||
|         </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> | ||||
|     <ai-dialog title="系统信息设置" :visible.sync="sysInfoDialog" width="600px" @onConfirm="submitSystemInfo" | ||||
|                @closed="sysInfo={}"> | ||||
|       <el-form size="small" label-width="140px"> | ||||
|         <el-form-item label="页签标题"> | ||||
|           <el-input v-model="sysInfo.title" placeholder="请输入..." clearable/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="系统标题"> | ||||
|           <el-input v-model="sysInfo.fullTitle" placeholder="请输入..." clearable/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="logo"> | ||||
|           <el-input v-model="sysInfo.logo" placeholder="请输入..." clearable/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="登录页左上角标题"> | ||||
|           <el-input v-model="sysInfo.name" placeholder="请输入..." clearable/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="登录页副标题"> | ||||
|           <el-input type="textarea" rows="5" v-model="sysInfo.desc" placeholder="请输入..." clearable/> | ||||
|         </el-form-item> | ||||
|  | ||||
|         <el-form-item label="版权所有"> | ||||
|           <el-input v-model="sysInfo.recordDesc" placeholder="请输入..." clearable/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="备案号"> | ||||
|           <el-input v-model="sysInfo.recordNo" placeholder="请输入..." clearable/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="备案跳转链接"> | ||||
|           <el-input v-model="sysInfo.recordURL" placeholder="请输入..." clearable/> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
| import AMapLoader from "@amap/amap-jsapi-loader" | ||||
|  | ||||
| export default { | ||||
|   name: "list", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {slot: 'expand'}, | ||||
|         {prop: "name", label: "名称"}, | ||||
|         {prop: "corpId", label: "企业微信ID", width: 180}, | ||||
|         {slot: "status",}, | ||||
|         {slot: "miniappStatus"}, | ||||
|         {prop: "createTime", label: "创建时间"}, | ||||
|         {slot: "options"}, | ||||
|       ] | ||||
|     }, | ||||
|     desConfigs() { | ||||
|       let isLine = true | ||||
|       return [ | ||||
|         {prop: "corpAddressBookSecret", label: "企业微信通讯录SECRET", width: 200}, | ||||
|         {prop: "corpAgentId", label: "企业微信AGENTID", width: 150}, | ||||
|         {prop: "corpSecret", label: "企业微信SECRET", isLine}, | ||||
|         {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: "areaId", label: "地区编码", width: 150, isLine}, | ||||
|         {prop: "lat", label: "纬度", width: 100}, | ||||
|         {prop: "lng", label: "经度", width: 100}, | ||||
|         {prop: "address", label: "中心点", width: 100, isLine}, | ||||
|         {prop: "webUrl", label: "管理端地址", width: 100}, | ||||
|         {prop: "dvcpUrl", label: "企微端地址", width: 100}, | ||||
|       ] | ||||
|     }, | ||||
|     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: "请填写企微访问域名"}], | ||||
|         webUrl: [{required: true, message: "请填写web访问域名"}], | ||||
|         status: [{required: true, message: "请选择状态", trigger: "change"}], | ||||
|         miniappStatus: [{required: true, message: "请选择小程序状态", trigger: "change"}], | ||||
|         areaId: [{required: true, message: "请选择地区", trigger: "change"}], | ||||
|         lat: [{required: true, message: "请选择中心点"}], | ||||
|         systemInfo: [{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: "" | ||||
|       }, | ||||
|       sysInfo: {}, | ||||
|       sysInfoDialog: false | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     selectMap() { | ||||
|       Object.keys(this.placeDetail).map(e => this.dialogForm[e] = this.placeDetail[e]); | ||||
|       this.showMap = false; | ||||
|     }, | ||||
|     initMap() { | ||||
|       AMapLoader.load({ | ||||
|         key: 'b553334ba34f7ac3cd09df9bc8b539dc', | ||||
|         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(); | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     onMiniappStatusChange(row) { | ||||
|       this.instance.post(`/app/appdvcpconfig/setMiniappStatus`, null, { | ||||
|         params: { | ||||
|           id: row.id, | ||||
|           status: row.miniappStatus | ||||
|         } | ||||
|       }).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.$message.success(+row.miniappStatus ? '已启用' : '已禁用'); | ||||
|           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(); | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleSystemInfo(id) { | ||||
|       this.sysInfoDialog = true | ||||
|       this.getSystemInfo(id) | ||||
|     }, | ||||
|     getSystemInfo(id) { | ||||
|       this.instance.post("/app/appdvcpconfig/getSystemInfo", null, { | ||||
|         params: {id} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.sysInfo = JSON.parse(res.data) | ||||
|           this.sysInfo.id = id | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     submitSystemInfo() { | ||||
|       let {id} = this.sysInfo | ||||
|       this.instance.post("/app/appdvcpconfig/updateSystemInfo", this.sysInfo, {params: {id}}).then(res => { | ||||
|         if (res?.code == 0) { | ||||
|           this.$message.success("提交成功!") | ||||
|           this.sysInfoDialog = false | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handlePush(id) { | ||||
|       this.instance.post("/app/appclapeventinfo/setAppWorkbench", null, {params: {id}}).then(res => { | ||||
|         if (res?.code == 0) { | ||||
|           this.$message.success("推送成功!") | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleTheme(id) { | ||||
|       this.$router.push({hash: "#theme", query: {id}}) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTableData() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .list { | ||||
|   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> | ||||
							
								
								
									
										83
									
								
								packages/core/AppQyWxConfig/themeSetting.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								packages/core/AppQyWxConfig/themeSetting.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| <template> | ||||
|   <section class="themeSetting"> | ||||
|     <ai-detail list> | ||||
|       <ai-title slot="title" title="主题样式" isShowBottomBorder isShowBack @back="cancel"> | ||||
|         <template #rightBtn> | ||||
|           <span class="mar-r8" v-text="'灰色滤镜'"/> | ||||
|           <el-switch size="mini" v-model="form.enableGreyFilter" name="灰色滤镜" border active-value="1" inactive-value="0"/> | ||||
|         </template> | ||||
|       </ai-title> | ||||
|       <template #content> | ||||
|         <el-form size="small" :model="form" ref="ThemeForm"> | ||||
|           <ai-title title="WEB后台"/> | ||||
|           <ai-select-card dict="themeWeb" v-model="form.colorScheme.web"/> | ||||
|         </el-form> | ||||
|       </template> | ||||
|       <template #footer> | ||||
|         <el-button @click="cancel">取消</el-button> | ||||
|         <el-button type="primary" @click="submit">提交</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AiSelectCard from "./components/AiSelectCard"; | ||||
|  | ||||
| export default { | ||||
|   name: "themeSetting", | ||||
|   components: {AiSelectCard}, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       form: {enableGreyFilter: '0', colorScheme: {}} | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getDetail() { | ||||
|       const {id} = this.$route.query | ||||
|       this.instance.post("/app/appdvcpconfig/detail", null, {params: {id}}).then(res => { | ||||
|         if (res?.data) { | ||||
|           let {colorScheme, enableGreyFilter} = res.data | ||||
|           colorScheme = JSON.parse(colorScheme) || {web: 'blue'} | ||||
|           this.form = {colorScheme, enableGreyFilter} | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     cancel() { | ||||
|       return this.$router.push({}) | ||||
|     }, | ||||
|     submit() { | ||||
|       this.$refs.ThemeForm.validate(v => { | ||||
|         if (v) { | ||||
|           let {colorScheme} = this.form | ||||
|           colorScheme = JSON.stringify(colorScheme) | ||||
|           this.instance.post("/app/appdvcpconfig/updateSysColorScheme", {...this.form, colorScheme}).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success("保存成功!") | ||||
|               this.cancel().then(() => location.reload()) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getDetail() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .themeSetting { | ||||
|   height: 100%; | ||||
|  | ||||
|   .mar-r8 { | ||||
|     margin-right: 8px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										443
									
								
								packages/core/AppRightsManager/AppRightsManager.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								packages/core/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
									
								
								packages/core/AppRightsManager/rightsAdd.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								packages/core/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?.code == 0) { | ||||
|               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
									
								
								packages/core/AppRightsManager/rightsGraph.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								packages/core/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
									
								
								packages/core/AppSystemAccount/AppSystemAccount.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								packages/core/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> | ||||
							
								
								
									
										193
									
								
								packages/core/AppUserInfo/AppUserInfo.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								packages/core/AppUserInfo/AppUserInfo.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| <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="姓名" :value="user.info.name"/> | ||||
|                 <ai-info-item label="手机号码" :value="user.info.phone"/> | ||||
|                 <ai-info-item label="角色" :value="user.info.roleName"/> | ||||
|                 <ai-info-item label="部门" :value="user.info.departName"/> | ||||
|                 <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> | ||||
		Reference in New Issue
	
	Block a user