目录代码整合
This commit is contained in:
		
							
								
								
									
										66
									
								
								packages/extra/AppAddressBook/AppAddressBook.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								packages/extra/AppAddressBook/AppAddressBook.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| <template> | ||||
|   <div class="doc-circulation ailist-wrapper"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import List from './components/List' | ||||
|   import Add from './components/Add' | ||||
|  | ||||
|   export default { | ||||
|     name: 'AppAddressBook', | ||||
|     label: '通讯录管理', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         component: 'List', | ||||
|         params: {}, | ||||
|         include: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       Add, | ||||
|       List | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onChange (data) { | ||||
|         if (data.type === 'Add') { | ||||
|           this.component = 'Add' | ||||
|           this.params = data.params | ||||
|         } | ||||
|  | ||||
|         if (data.type === 'list') { | ||||
|           this.component = 'List' | ||||
|           this.params = data.params | ||||
|  | ||||
|           this.$nextTick(() => { | ||||
|             if (data.isRefresh) { | ||||
|               this.$refs.component.getList() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
|   .doc-circulation { | ||||
|     height: 100%; | ||||
|     background: #F3F6F9; | ||||
|     overflow: auto; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										203
									
								
								packages/extra/AppAddressBook/components/Add.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								packages/extra/AppAddressBook/components/Add.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| <template> | ||||
|   <ai-detail> | ||||
|     <template slot="title"> | ||||
|       <ai-title :title="id ? '编辑成员' : '添加成员'" isShowBack isShowBottomBorder @onBackClick="cancel(false)"> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|       <ai-card title="个人信息"> | ||||
|         <template #content> | ||||
|           <div class="ai-form"> | ||||
|             <el-form-item label="姓名" prop="name" :rules="[{ required: true, message: '请输入姓名', trigger: 'blur' }]"> | ||||
|               <el-input size="small" placeholder="请输入姓名" show-word-limit v-model="form.name" :maxlength="10"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="账号" prop="id" :rules="[{ required: true, message: '请输入账号', trigger: 'blur' }]"> | ||||
|               <el-input size="small" :disabled="!!id" show-word-limit :maxlength="30" placeholder="成员唯一标识,设定以后不支持修改" v-model="form.id"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="手机号" prop="mobile" :rules="[{ required: true, validator: validatorPhone, trigger: 'blur' }]"> | ||||
|               <el-input size="small" placeholder="请输入手机号" show-word-limit :maxlength="11" v-model="form.mobile"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="性别" prop="gender"> | ||||
|               <el-radio-group v-model="form.gender"> | ||||
|                 <el-radio label="1">男</el-radio> | ||||
|                 <el-radio label="2">女</el-radio> | ||||
|               </el-radio-group> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="座机" prop="telephone"> | ||||
|               <el-input size="small" placeholder="请输入座机" v-model="form.telephone"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="邮箱" prop="email"> | ||||
|               <el-input size="small" placeholder="请输入邮箱" v-model="form.email"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="地址" style="width: 100%;" prop="address"> | ||||
|               <el-input size="small" style="width: 100%;" show-word-limit :maxlength="30" placeholder="请输入地址" v-model="form.address"></el-input> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       <ai-card title="组织信息"> | ||||
|         <template #content> | ||||
|           <el-form-item label="部门" prop="departmentName" style="width: 100%;" :rules="[{ required: true, message: '请选择部门', trigger: 'change' }]"> | ||||
|             <el-input size="small" placeholder="请选择..." disabled v-model="form.departmentName"> | ||||
|               <ai-wechat-selecter slot="append" isStrictly :instance="instance" @change="onChange" v-model="department" isChooseUnit> | ||||
|                 <el-button type="info">选择</el-button> | ||||
|               </ai-wechat-selecter> | ||||
|             </el-input> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="标签" style="width: 100%;" prop="tags"> | ||||
|             <el-select size="small" v-model="form.tagIds" multiple placeholder="请选择标签"> | ||||
|               <el-option | ||||
|                 v-for="item in tagsList" | ||||
|                 :key="item.id" | ||||
|                 :label="item.tagname" | ||||
|                 :value="item.id"> | ||||
|               </el-option> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="职务" prop="position"> | ||||
|             <el-input size="small" placeholder="请输入职务" v-model="form.position"></el-input> | ||||
|           </el-form-item> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       </el-form> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button @click="cancel">取消</el-button> | ||||
|       <el-button type="primary" @click="confirm">提交</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'Add', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       params: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       const validatorPhone = function (rule, value, callback) { | ||||
|         if (value === '') { | ||||
|           callback(new Error('请输入手机号')) | ||||
|         } else if (!/^1\d{10}$/.test(value)) { | ||||
|           callback(new Error('手机号格式错误')) | ||||
|         } else { | ||||
|           callback() | ||||
|         } | ||||
|       } | ||||
|       return { | ||||
|         info: {}, | ||||
|         department: [], | ||||
|         validatorPhone: validatorPhone, | ||||
|         form: { | ||||
|           position: '', | ||||
|           name: '', | ||||
|           email: '', | ||||
|           telephone: '', | ||||
|           gender: '', | ||||
|           mobile: '', | ||||
|           departmentName: '', | ||||
|           departmentIds: [], | ||||
|           tagIds: [], | ||||
|           id: '' | ||||
|         }, | ||||
|         id: '', | ||||
|         tagsList: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.getTags() | ||||
|  | ||||
|       if (this.params && this.params.departmentId && !this.params.id) { | ||||
|         this.department = [{ | ||||
|           id: String(this.params.departmentId), | ||||
|           name: this.params.departmentName | ||||
|         }] | ||||
|         this.form.departmentIds = [this.params.departmentId] | ||||
|         this.form.departmentName = this.params.departmentName | ||||
|       } | ||||
|  | ||||
|       if (this.params && this.params.id) { | ||||
|         this.id = this.params.id | ||||
|         this.getInfo(this.params.id) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getInfo (id) { | ||||
|         this.instance.post(`/app/wxcp/wxuser/queryDetailById?id=${id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             const departmentNames = res.data.departmentNames.split(',') | ||||
|             this.department = res.data.departmentIdsStr.split(',').map((item, index) => { | ||||
|               return { | ||||
|                 name: departmentNames[index], | ||||
|                 id: item | ||||
|               } | ||||
|             }) | ||||
|             this.form = { | ||||
|               ...res.data, | ||||
|               departmentName: res.data.departmentNames, | ||||
|               tagIds: res.data.tags.map(v => v.id), | ||||
|               departmentIds: res.data.departmentIdsStr.split(',') | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onChange (e) { | ||||
|         if (e.length) { | ||||
|           this.form.departmentIds = e.map(v => v.id) | ||||
|           this.form.departmentName = e.map(v => v.name).join(',') | ||||
|         } else { | ||||
|           this.form.departmentIds = '' | ||||
|           this.form.departmentName = '' | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       getTags () { | ||||
|         this.instance.post(`/app/wxcp/wxtag/listAll`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.tagsList = res.data | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onClose () { | ||||
|         this.form.explain = '' | ||||
|       }, | ||||
|  | ||||
|       confirm () { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             const api = this.id ? '/app/wxcp/wxuser/update' : '/app/wxcp/wxuser/add' | ||||
|             this.instance.post(api, { | ||||
|               ...this.form | ||||
|             }).then(res => { | ||||
|               if (res.code == 0) { | ||||
|                 this.$message.success('提交成功') | ||||
|                 setTimeout(() => { | ||||
|                   this.cancel(true) | ||||
|                 }, 600) | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       cancel (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'list', | ||||
|           isRefresh: !!isRefresh | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| </style> | ||||
							
								
								
									
										987
									
								
								packages/extra/AppAddressBook/components/List.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										987
									
								
								packages/extra/AppAddressBook/components/List.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,987 @@ | ||||
| <template> | ||||
|   <ai-list class="addressBook"> | ||||
|     <template slot="title"> | ||||
|       <ai-title title="内部通讯录" isShowBottomBorder></ai-title> | ||||
|     </template> | ||||
|     <template #left> | ||||
|       <div class="addressBook-left"> | ||||
|         <div class="addressBook-left__title"> | ||||
|           <h2 @click="tabIndex = 0, search.current = 1, getList()" :class="[tabIndex === 0 ? 'tab-active' : '']"> | ||||
|             组织架构</h2> | ||||
|           <h2 @click="tabIndex = 1, search.current = 1, getList()" :class="[tabIndex === 1 ? 'tab-active' : '']">标签</h2> | ||||
|         </div> | ||||
|         <div class="addressBook-left__list--title" v-if="tabIndex === 0"> | ||||
|           <el-input | ||||
|               size="mini" | ||||
|               placeholder="请输入部门名称" | ||||
|               v-model="unitName" | ||||
|               clearable | ||||
|               suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </div> | ||||
|         <div class="addressBook-left__list--title" v-if="tabIndex === 1"> | ||||
|           <el-button size="mini" icon="iconfont iconAdd" @click="isShowTags = true">添加标签</el-button> | ||||
|           <el-input | ||||
|               class="addressBook-left__list--search" | ||||
|               size="mini" | ||||
|               clearable | ||||
|               style="width: 154px;" | ||||
|               placeholder="请输入标签名称" | ||||
|               v-model="tagName" | ||||
|               suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </div> | ||||
|         <div class="addressBook-left__list--wrapper"> | ||||
|           <div class="addressBook-left__list" v-show="tabIndex === 0"> | ||||
|             <el-tree | ||||
|               :filter-node-method="filterNode" | ||||
|               ref="tree" | ||||
|               :props="defaultProps" | ||||
|               node-key="id" | ||||
|               :data="unitList" | ||||
|               highlight-current | ||||
|               @node-contextmenu="nodeContextmenu" | ||||
|               :current-node-key="search.departmentId" | ||||
|               :default-expanded-keys="defaultExpanded" | ||||
|               :default-checked-keys="defaultChecked" | ||||
|               @current-change="onTreeChange"> | ||||
|             </el-tree> | ||||
|             <ul | ||||
|                 v-if="isShowMenu" | ||||
|                 class="el-dropdown-menu el-popper" | ||||
|                 :style="{top: menuInfo.y + 'px', left: menuInfo.x + 'px', position: 'fixed', zIndex: 2023}" | ||||
|                 x-placement="top-end"> | ||||
|               <li class="el-dropdown-menu__item" @click="handleTreeCommand('add', menuInfo.node)">添加子部门</li> | ||||
|               <li class="el-dropdown-menu__item" @click="handleTreeCommand('edit', menuInfo.node)">修改名称</li> | ||||
|               <li class="el-dropdown-menu__item" @click="handleTreeCommand('remove', menuInfo.node)">删除</li> | ||||
|               <li class="el-dropdown-menu__item" :class="[!menuInfo.node.i ? 'is-disabled' : '']" | ||||
|                   @click="handleTreeCommand('top', menuInfo.node)">上移 | ||||
|               </li> | ||||
|               <li | ||||
|                   class="el-dropdown-menu__item" | ||||
|                   :class="[(menuInfo.node.i === menuInfo.node.len - 1) || (!menuInfo.node.i && menuInfo.node.i !== 0) ? 'is-disabled' : '']" | ||||
|                   @click="handleTreeCommand('bottom', menuInfo.node)">下移 | ||||
|               </li> | ||||
|             </ul> | ||||
|           </div> | ||||
|           <div class="addressBook-left__list" v-show="tabIndex === 1"> | ||||
|             <div class="addressBook-left__tags"> | ||||
|               <div | ||||
|                   @click="changeTag(index)" | ||||
|                   class="addressBook-left__tags--item" | ||||
|                   :class="[currIndex === index ? 'addressBook-left__tags--item-active' : '']" | ||||
|                   v-for="(item, index) in tagsList" :key="index"> | ||||
|                 <span>{{ item.tagname }}</span> | ||||
|                 <el-dropdown @command="e => handleCommand(e, item)"> | ||||
|                   <i class="iconfont iconmore"></i> | ||||
|                   <el-dropdown-menu slot="dropdown"> | ||||
|                     <el-dropdown-item command="edit">编辑</el-dropdown-item> | ||||
|                     <el-dropdown-item command="remove">删除</el-dropdown-item> | ||||
|                   </el-dropdown-menu> | ||||
|                 </el-dropdown> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar class="search-bar"> | ||||
|         <template #left> | ||||
|           <el-button size="small" type="primary" icon="iconfont iconAdd" v-if="tabIndex === 0" @click="toAdd('')">添加成员 | ||||
|           </el-button> | ||||
|           <ai-import :instance="instance" :dict="dict" v-if="tabIndex === 0" type="wxcp/wxuser" name="内部通讯录" | ||||
|                      :importParams="{departmentId:search.departmentId}" @success="getList"/> | ||||
|           <el-button size="small" icon="iconfont iconUpdate_Files" v-if="tabIndex === 0" :loading="btnLoading" | ||||
|                      @click="syncMembers">同步数据 | ||||
|           </el-button> | ||||
|           <ai-wechat-selecter refs="addTags" :instance="instance" v-model="users" @change="onChooseUser" | ||||
|                               :disabled="currIndex < 0" v-if="tabIndex === 1"> | ||||
|             <el-button size="small" :disabled="currIndex < 0" type="primary" icon="iconfont iconAdd">添加成员</el-button> | ||||
|           </ai-wechat-selecter> | ||||
|         </template> | ||||
|         <template slot="right"> | ||||
|           <el-input | ||||
|               v-model="search.name" | ||||
|               size="small" | ||||
|               v-throttle="() => {search.current = 1, getList()}" | ||||
|               placeholder="请输入成员姓名、手机号或标签名称" | ||||
|               clearable | ||||
|               @clear="search.current = 1, search.name = '', getList()" | ||||
|               suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table | ||||
|           :tableData="tableData" | ||||
|           :col-configs="colConfigs" | ||||
|           :total="total" | ||||
|           v-loading="loading" | ||||
|           style="margin-top: 6px;" | ||||
|           :current.sync="search.current" | ||||
|           :size.sync="search.size" | ||||
|           @handleSelectionChange="handleSelectionChange" | ||||
|           @getList="getList"> | ||||
|         <el-table-column slot="avatar" label="" align="right" width="100px"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <img class="table-avatar" :src="row.avatar || 'https://cdn.cunwuyun.cn/dvcp/h5/defaultAvatar.png'"> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column slot="tags" label="标签" align="left"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-tags" v-if="row.tagNames"> | ||||
|               <el-tag type="info" v-for="(item, index) in row.tagNames.split('、')" size="small" :key="index">{{ | ||||
|                   item | ||||
|                 }} | ||||
|               </el-tag> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column slot="options" width="140px" fixed="right" label="操作" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-options"> | ||||
|               <el-button type="text" @click="toAdd(row.id)" v-show="tabIndex === 0">编辑</el-button> | ||||
|               <el-button type="text" @click="remove(row.id)" v-show="tabIndex === 0">删除</el-button> | ||||
|               <el-button type="text" @click="removeTags(row.id)" v-show="tabIndex === 1">移除</el-button> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <div slot="paginationBtns" class="addressBook-table__btns"> | ||||
|           <span style="margin-right: 8px;" @click="removeAll">{{ tabIndex === 0 ? '批量删除' : '批量移除' }}</span> | ||||
|           <ai-wechat-selecter :instance="instance" v-model="department" isChooseUnit @change="onDepartment" | ||||
|                               v-if="tabIndex === 0"> | ||||
|             <span>批量导出</span> | ||||
|           </ai-wechat-selecter> | ||||
|         </div> | ||||
|       </ai-table> | ||||
|       <ai-dialog | ||||
|           :visible.sync="isShowTags" | ||||
|           width="590px" | ||||
|           :title="tagId ? '编辑标签' : '添加标签'" | ||||
|           @close="onClose" | ||||
|           @onConfirm="onFormConfirm"> | ||||
|         <el-form ref="tagForm" :model="tagForm" label-width="110px" label-position="right"> | ||||
|           <el-form-item label="标签名称" prop="tagname" :rules="[{ required: true, message: '请输入标签名称', trigger: 'blur' }]"> | ||||
|             <el-input size="small" placeholder="请输入标签名称" show-word-limit :maxlength="10" v-model="tagForm.tagname"></el-input> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|       <ai-dialog | ||||
|           :visible.sync="isShowDepart" | ||||
|           width="590px" | ||||
|           :title="departId ? '修改名称' : '添加部门'" | ||||
|           @close="onClose" | ||||
|           @onConfirm="onDepartConfirm"> | ||||
|         <el-form ref="departForm" :model="departForm" label-width="110px" label-position="right"> | ||||
|           <el-form-item label="部门名称" prop="name" :rules="[{ required: true, message: '请输入部门名称', trigger: 'blur' }]"> | ||||
|             <el-input size="small" placeholder="请输入部门名称" show-word-limit :maxlength="30" v-model="departForm.name"></el-input> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'List', | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       users: [], | ||||
|       isShowMenu: false, | ||||
|       department: [], | ||||
|       btnLoading: false, | ||||
|       menuInfo: { | ||||
|         x: '', | ||||
|         y: '', | ||||
|         node: {} | ||||
|       }, | ||||
|       search: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|         title: '', | ||||
|         tagname: '', | ||||
|         name: '', | ||||
|         tagIds: '', | ||||
|         departmentId: '' | ||||
|       }, | ||||
|       tagForm: { | ||||
|         tagname: '' | ||||
|       }, | ||||
|       isShowDepart: false, | ||||
|       departForm: { | ||||
|         name: '' | ||||
|       }, | ||||
|       loading: false, | ||||
|       isShowTags: false, | ||||
|       defaultChecked: [], | ||||
|       defaultExpanded: [], | ||||
|       tabIndex: 0, | ||||
|       currIndex: -1, | ||||
|       areaList: [], | ||||
|       total: 0, | ||||
|       colConfigs: [ | ||||
|         {type: 'selection', label: ''}, | ||||
|         {slot: 'avatar', label: ''}, | ||||
|         {prop: 'name', label: '姓名'}, | ||||
|         {prop: 'position', label: '职务'}, | ||||
|         {prop: 'departmentNames', label: '部门'}, | ||||
|         {prop: 'mobile', label: '手机号'}, | ||||
|         {slot: 'tags', label: '标签'}, | ||||
|         {prop: 'status', label: '账号状态', align: 'center', formart: v => v === 1 ? '已激活' : '未激活'} | ||||
|       ], | ||||
|       defaultProps: { | ||||
|         children: 'children', | ||||
|         label: 'name' | ||||
|       }, | ||||
|       unitName: '', | ||||
|       rootId: '', | ||||
|       unitList: [], | ||||
|       tagsList: [], | ||||
|       tagName: '', | ||||
|       sourceTagList: [], | ||||
|       tableData: [], | ||||
|       tagId: '', | ||||
|       departmentName: '', | ||||
|       departId: '', | ||||
|       ids: '' | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']) | ||||
|   }, | ||||
|  | ||||
|   watch: { | ||||
|     unitName(val) { | ||||
|       this.$refs.tree.filter(val) | ||||
|     }, | ||||
|  | ||||
|     tagName(val) { | ||||
|       if (!val) { | ||||
|         this.tagsList = this.sourceTagList | ||||
|       } | ||||
|  | ||||
|       this.tagsList = this.sourceTagList.filter(v => v.tagname.indexOf(val) > -1) | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     this.getTree() | ||||
|     this.getList() | ||||
|     this.getTags() | ||||
|     document.querySelector('html').addEventListener('click', this.bindEvent) | ||||
|  | ||||
|     this.$nextTick(() => { | ||||
|     }) | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     changeTag(index) { | ||||
|       this.currIndex = index | ||||
|       this.search.current = 1 | ||||
|  | ||||
|       this.$nextTick(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     bindEvent() { | ||||
|       this.isShowMenu = false | ||||
|     }, | ||||
|  | ||||
|     nodeContextmenu(e, node) { | ||||
|       this.isShowMenu = true | ||||
|       let y = e.y + 6 | ||||
|       if (y + 202 > document.body.clientHeight) { | ||||
|         y = y - 202 | ||||
|       } | ||||
|       this.menuInfo = { | ||||
|         x: e.x + 16, y, | ||||
|         node | ||||
|       } | ||||
|     }, | ||||
|     removeTags(id) { | ||||
|       if (this.currIndex < 0) { | ||||
|         return this.$message.error('请选择标签') | ||||
|       } | ||||
|  | ||||
|       this.$confirm('确定移除该成员?').then(() => { | ||||
|         this.instance.post(`/app/wxcp/wxtag/removeTag?userIds=${id}&tagId=${this.tagsList[this.currIndex].id}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('移除成功!') | ||||
|             this.search.current = 1 | ||||
|  | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onDepartment(e) { | ||||
|       if (!e.length) { | ||||
|         return this.$message.error('请选择部门') | ||||
|       } | ||||
|       const ids = e.map(v => v.id).join(',') | ||||
|  | ||||
|       this.department = [] | ||||
|       this.instance.post(`/app/wxcp/wxuser/export?departmentId=${ids}`, null, { | ||||
|         responseType: 'blob' | ||||
|       }).then(res => { | ||||
|         if (res?.type == "application/json") { | ||||
|           let reader = new FileReader() | ||||
|           reader.readAsText(res, "utf-8") | ||||
|           reader.onload = e => { | ||||
|             if (e.target.readyState === 2) { | ||||
|               let ret = JSON.parse(e.target.result) | ||||
|               if (ret?.code == 0) { | ||||
|                 this.$message.success(ret.msg) | ||||
|               } else this.$message.error(ret.msg) | ||||
|             } | ||||
|           } | ||||
|         } else { | ||||
|           const link = document.createElement('a') | ||||
|           let blob = new Blob([res], {type: res.type}) | ||||
|           link.style.display = 'none' | ||||
|           link.href = URL.createObjectURL(blob) | ||||
|           link.setAttribute('download', `${e[0].name}.xls`) | ||||
|           document.body.appendChild(link) | ||||
|           link.click() | ||||
|           document.body.removeChild(link) | ||||
|           this.$message.success('导出成功!') | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onChooseUser(e) { | ||||
|       if (!e.length) { | ||||
|         return this.$message.error('请选择成员') | ||||
|       } | ||||
|  | ||||
|       this.instance.post(`/app/wxcp/wxtag/markTag`, null, { | ||||
|         params: { | ||||
|           tagId: this.tagsList[this.currIndex].id, | ||||
|           userIds: e.map(v => v.id).join(',') | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.getList() | ||||
|           this.users = [] | ||||
|           this.search.current = 1 | ||||
|           this.$refs.addTags.reset() | ||||
|         } else { | ||||
|           this.users = [] | ||||
|         } | ||||
|       }).catch(() => { | ||||
|         this.users = [] | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     handleTreeCommand(e, item) { | ||||
|       this.isShowMenu = false | ||||
|  | ||||
|       if (e === 'add') { | ||||
|         this.departForm.id = '' | ||||
|         this.departForm.parentid = item.id | ||||
|         this.departId = '' | ||||
|         this.isShowDepart = true | ||||
|       } else if (e === 'edit') { | ||||
|         this.departForm = { | ||||
|           ...item | ||||
|         } | ||||
|  | ||||
|         this.departId = item.id | ||||
|         this.isShowDepart = true | ||||
|       } else if (e === 'top') { | ||||
|         if (!item.i) { | ||||
|           return false | ||||
|         } | ||||
|  | ||||
|         this.moveDepart(item.id, 0) | ||||
|       } else if (e === 'bottom') { | ||||
|         if ((item.i === item.len - 1) || (!item.i && item.i !== 0)) { | ||||
|           return false | ||||
|         } | ||||
|  | ||||
|         this.moveDepart(item.id, 1) | ||||
|       } else if (e === 'remove') { | ||||
|         this.removeDepart(item.id, item.parentid) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     removeDepart(id, parentid) { | ||||
|       this.$confirm('确定删除该数据?').then(() => { | ||||
|         this.instance.post(`/app/wxcp/wxdepartment/delete?id=${id}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.defaultChecked = [parentid] | ||||
|             this.$message.success('删除成功!') | ||||
|             this.getTree() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     moveDepart(id, type) { | ||||
|       this.instance.post(`/app/wxcp/wxdepartment/move?id=${id}&type=${type}`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.defaultChecked = [id] | ||||
|           this.getTree() | ||||
|           this.$message.success(type === 0 ? '上移成功' : '下移成功') | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onDepartConfirm() { | ||||
|       this.$refs.departForm.validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.instance.post(`/app/wxcp/wxdepartment/addOrUpdate`, { | ||||
|             ...this.departForm, | ||||
|             departId: this.departId | ||||
|           }).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.defaultChecked = [this.departForm.parentid] | ||||
|               this.isShowDepart = false | ||||
|               this.getTree() | ||||
|               this.$message.success(this.departId ? '编辑成功' : '新增成功') | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onFormConfirm() { | ||||
|       this.$refs.tagForm.validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.instance.post(`/app/wxcp/wxtag/addOrUpdate`, { | ||||
|             ...this.tagForm | ||||
|           }).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.isShowTags = false | ||||
|               this.getTags() | ||||
|               this.$message.success(this.tagId ? '编辑成功' : '新增成功') | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     handleCommand(e, item) { | ||||
|       if (e === 'edit') { | ||||
|         this.tagId = item.id | ||||
|         this.tagForm = { | ||||
|           ...item | ||||
|         } | ||||
|  | ||||
|         this.isShowTags = true | ||||
|       } else { | ||||
|         this.$confirm('确定删除该数据?').then(() => { | ||||
|           this.instance.post(`/app/wxcp/wxtag/delete?id=${item.id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.getTags() | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     onClose() { | ||||
|       this.tagId = '' | ||||
|       this.tagForm.tagname = '' | ||||
|       this.departForm.name = '' | ||||
|       this.departId = '' | ||||
|       this.departForm.nameEn = '' | ||||
|       this.departForm.parentid = '' | ||||
|       this.departForm.showIndex = '' | ||||
|     }, | ||||
|  | ||||
|     syncMembers() { | ||||
|       let departId = this.search.departmentId; | ||||
|       if (!departId) departId = 1; | ||||
|       this.btnLoading = true | ||||
|  | ||||
|       this.instance.post(`/app/wxcp/wxdepartment/syncDepart`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.instance.post(`/app/wxcp/wxdepartment/syncUser?departmentId=${departId}`, null, { | ||||
|             timeout: 1000000 | ||||
|           }).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('同步成功') | ||||
|               this.getList() | ||||
|               this.getTree() | ||||
|             } | ||||
|  | ||||
|             this.btnLoading = false | ||||
|           }).catch(() => { | ||||
|             this.btnLoading = false | ||||
|           }) | ||||
|         } | ||||
|  | ||||
|       }).catch(() => { | ||||
|         this.btnLoading = false | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     getTags() { | ||||
|       this.instance.post(`/app/wxcp/wxtag/listAll`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.sourceTagList = res.data.length ? JSON.parse(JSON.stringify(res.data)) : [] | ||||
|           this.tagsList = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onSwitchChange(id) { | ||||
|       this.instance.post(`/app/wxcp/wxuser/enable?id=${id}`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.getList() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onTreeChange(e) { | ||||
|       this.departmentName = e.name | ||||
|       this.search.departmentId = e.id || '' | ||||
|       this.search.current = 1 | ||||
|       this.isShowMenu = false | ||||
|  | ||||
|       this.$nextTick(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     getList() { | ||||
|       this.loading = true | ||||
|       this.instance.post(`/app/wxcp/wxuser/list`, null, { | ||||
|         params: { | ||||
|           ...this.search, | ||||
|           departmentId: this.tabIndex === 0 ? this.search.departmentId : '', | ||||
|           tagIds: this.tabIndex === 1 ? (this.currIndex >= 0 ? this.tagsList[this.currIndex].id : '') : '', | ||||
|           listType: this.tabIndex | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.tableData = res.data.records | ||||
|           this.total = res.data.total | ||||
|  | ||||
|           this.$nextTick(() => { | ||||
|             this.loading = false | ||||
|           }) | ||||
|         } else { | ||||
|           this.loading = false | ||||
|         } | ||||
|       }).catch(() => { | ||||
|         this.loading = false | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     removeAll() { | ||||
|       if (!this.ids) return | ||||
|  | ||||
|       if (this.tabIndex === 1) { | ||||
|         this.removeTags(this.ids) | ||||
|       } else { | ||||
|         this.remove(this.ids) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     handleSelectionChange(e) { | ||||
|       this.ids = e.map(v => v.id).join(',') | ||||
|     }, | ||||
|  | ||||
|     filterNode(value, data) { | ||||
|       if (!value) return true | ||||
|       return data.name.indexOf(value) !== -1 | ||||
|     }, | ||||
|  | ||||
|     changeTab(id, index) { | ||||
|       this.currIndex = index | ||||
|       this.search.areaId = id | ||||
|  | ||||
|       this.$nextTick(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     getTree() { | ||||
|       this.instance.post(`/app/wxcp/wxdepartment/listAll?unitName=${this.unitName}`).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           let parent = res.data.map(v => { | ||||
|             v.label = v.name | ||||
|             v.children = [] | ||||
|  | ||||
|             return v | ||||
|           }).filter(e => !e.parentid)[0] | ||||
|           this.defaultExpanded = [parent.id] | ||||
|           this.defaultChecked = [parent.id] | ||||
|           this.search.departmentId = parent.id | ||||
|           this.departmentName = parent.name | ||||
|           this.addChild(parent, res.data) | ||||
|           this.unitList = [parent] | ||||
|  | ||||
|           this.$nextTick(() => { | ||||
|             this.$refs.tree.setCurrentKey(parent.id) | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     addChild(parent, list) { | ||||
|       for (let i = 0; i < list.length; i++) { | ||||
|         if (list[i].parentid === parent.id) { | ||||
|           list[i].i = parent.children.length | ||||
|           parent.children.push(list[i]) | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (parent.children.length) { | ||||
|         parent.children.forEach(v => { | ||||
|           v.len = parent.children.length | ||||
|         }) | ||||
|       } | ||||
|  | ||||
|       if (list.length > 0) { | ||||
|         parent['children'].map(v => this.addChild(v, list)) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     formatList(list) { | ||||
|       var arr = [] | ||||
|       for (let item of list) { | ||||
|         if (item.childrenUser && item.childrenUser.length) { | ||||
|           delete item.childrenUser | ||||
|         } | ||||
|  | ||||
|         if (item.childrenDept && item.childrenDept.length) { | ||||
|           this.formatList(item.childrenDept) | ||||
|         } | ||||
|  | ||||
|         arr.push(item) | ||||
|       } | ||||
|  | ||||
|       return arr | ||||
|     }, | ||||
|  | ||||
|     remove(id) { | ||||
|       this.$confirm('确定删除该数据?').then(() => { | ||||
|         this.instance.post(`/app/wxcp/wxuser/delete?id=${id}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('删除成功!') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     toAdd(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'Add', | ||||
|         params: { | ||||
|           id: id || '', | ||||
|           departmentId: this.search.departmentId || '', | ||||
|           departmentName: this.departmentName || '' | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .addressBook { | ||||
|   .addressBook-table__btns { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   .table-tags { | ||||
|     .el-tag { | ||||
|       margin-right: 8px; | ||||
|       margin-bottom: 8px; | ||||
|  | ||||
|       &:last-child { | ||||
|         margin-right: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .import-wrapper { | ||||
|     & > h2 { | ||||
|       margin-bottom: 8px; | ||||
|       font-size: 16px; | ||||
|       color: #222222; | ||||
|       font-weight: Bold; | ||||
|     } | ||||
|  | ||||
|     .import-wrapper__tips { | ||||
|       line-height: 1; | ||||
|       margin-bottom: 24px; | ||||
|  | ||||
|       div { | ||||
|         display: flex; | ||||
|         margin-bottom: 8px; | ||||
|         color: #222222; | ||||
|         font-size: 14px; | ||||
|  | ||||
|         span { | ||||
|           cursor: pointer; | ||||
|           color: #2266FF; | ||||
|  | ||||
|           &:hover { | ||||
|             opacity: 0.8; | ||||
|             text-decoration: underline; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .import-files { | ||||
|       i { | ||||
|         display: block; | ||||
|         margin-top: 8px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     i { | ||||
|       color: #999999; | ||||
|       font-size: 12px; | ||||
|       font-style: normal; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .tree-container { | ||||
|     position: relative; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: space-between; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|  | ||||
|     .tree-name { | ||||
|       padding-right: 30px; | ||||
|     } | ||||
|  | ||||
|     i { | ||||
|       position: absolute; | ||||
|       top: 50%; | ||||
|       right: 8px; | ||||
|       transform: translateY(-50%); | ||||
|       padding-right: 8px; | ||||
|       font-weight: normal; | ||||
|       color: #fff; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .el-tag { | ||||
|     margin-right: 8px; | ||||
|     border: 1px solid #D0D4DC; | ||||
|     background: #F3F4F7; | ||||
|     border-radius: 4px; | ||||
|     font-size: 13px; | ||||
|     color: #222222; | ||||
|  | ||||
|     &:last-child { | ||||
|       margin-right: 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .table-avatar { | ||||
|     width: 40px; | ||||
|     height: 40px; | ||||
|     margin-top: 3px; | ||||
|     border-radius: 2px; | ||||
|     border: 1px solid #CCCCCC; | ||||
|   } | ||||
|  | ||||
|   .el-button--mini, .el-button--mini.is-round { | ||||
|     height: 28px; | ||||
|     line-height: 28px; | ||||
|     padding: 0; | ||||
|     font-size: 12px; | ||||
|  | ||||
|     ::v-deep span { | ||||
|       margin-left: 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .addressBook-left__list--title { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     margin: 8px 8px 0; | ||||
|  | ||||
|     .addressBook-left__list--search { | ||||
|       flex: 1; | ||||
|  | ||||
|       ::v-deep input { | ||||
|         width: 100%; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .el-button { | ||||
|       width: 84px; | ||||
|       flex-shrink: 1; | ||||
|       margin-right: 8px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .addressBook-left { | ||||
|     width: 100%; | ||||
|     height: auto; | ||||
|     background: #FAFAFB; | ||||
|  | ||||
|     .addressBook-left__title { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       width: 100%; | ||||
|       height: 40px; | ||||
|       background: #ffffff; | ||||
|  | ||||
|       h2 { | ||||
|         flex: 1; | ||||
|         height: 100%; | ||||
|         line-height: 40px; | ||||
|         color: #222; | ||||
|         font-size: 14px; | ||||
|         text-align: center; | ||||
|         cursor: pointer; | ||||
|         border-bottom: 2px solid transparent; | ||||
|  | ||||
|         &.tab-active { | ||||
|           color: #2266FF; | ||||
|           border-bottom: 2px solid #2266FF; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // ::-webkit-scrollbar { | ||||
|     //   width: 1px; | ||||
|     // } | ||||
|  | ||||
|     .addressBook-left__list--wrapper { | ||||
|       height: calc(100% - 68px); | ||||
|       padding: 8px; | ||||
|     } | ||||
|  | ||||
|     .addressBook-left__list { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|       overflow: auto; | ||||
|  | ||||
|       ::v-deep .el-tree { | ||||
|         width: fit-content; | ||||
|         min-width: 100%; | ||||
|       } | ||||
|  | ||||
|       ::v-deep .el-scrollbar__wrap { | ||||
|         margin-bottom: 0 !important; | ||||
|         overflow-x: hidden; | ||||
|  | ||||
|         .el-scrollbar__view { | ||||
|           width: fit-content; | ||||
|           min-width: 100%; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .addressBook-left__tags--item { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         justify-content: space-between; | ||||
|         height: 40px; | ||||
|         padding: 0 8px 0 16px; | ||||
|         cursor: pointer; | ||||
|         color: #222222; | ||||
|  | ||||
|         &.addressBook-left__tags--item-active, &:hover { | ||||
|           background: #E8EFFF; | ||||
|           color: #2266FF; | ||||
|  | ||||
|           i, span { | ||||
|             color: #2266FF; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         span { | ||||
|           font-size: 14px; | ||||
|         } | ||||
|  | ||||
|         i { | ||||
|           cursor: pointer; | ||||
|           color: #8e9ebf; | ||||
|           font-size: 16px; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       span { | ||||
|         color: #222222; | ||||
|         font-size: 14px; | ||||
|       } | ||||
|  | ||||
|       ::v-deep .el-tree { | ||||
|         background: transparent; | ||||
|  | ||||
|         .el-tree-node__expand-icon.is-leaf { | ||||
|           color: transparent !important; | ||||
|         } | ||||
|  | ||||
|         .el-tree-node__content > .el-tree-node__expand-icon { | ||||
|           padding: 4px; | ||||
|         } | ||||
|  | ||||
|         .el-tree-node__content { | ||||
|           height: 32px; | ||||
|         } | ||||
|  | ||||
|         .el-tree__empty-text { | ||||
|           color: #222; | ||||
|           font-size: 14px; | ||||
|         } | ||||
|  | ||||
|         .el-tree-node__children .el-tree-node__content { | ||||
|           height: 32px; | ||||
|         } | ||||
|  | ||||
|         .el-tree-node__content:hover { | ||||
|           background: #E8EFFF; | ||||
|           color: #222222; | ||||
|           border-radius: 2px; | ||||
|         } | ||||
|  | ||||
|         .is-current > .el-tree-node__content { | ||||
|           &:hover { | ||||
|             background: #2266FF; | ||||
|             color: #fff; | ||||
|           } | ||||
|  | ||||
|           background: #2266FF; | ||||
|  | ||||
|           span { | ||||
|             color: #fff; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-list__content--right { | ||||
|     flex: 1; | ||||
|     min-width: 0; | ||||
|     margin-left: 1px; | ||||
|     box-shadow: none; | ||||
|  | ||||
|     .ai-list__content--right-wrapper { | ||||
|       width: 100%; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										304
									
								
								packages/extra/AppCarousel/AppCarousel.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								packages/extra/AppCarousel/AppCarousel.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,304 @@ | ||||
| <template> | ||||
|   <div class="appcarousel"> | ||||
|     <ai-list> | ||||
|       <template slot="title"> | ||||
|         <ai-title title="轮播图片" :isShowBottomBorder="false" :isShowArea="false"></ai-title> | ||||
|       </template> | ||||
|  | ||||
|       <template slot="content"> | ||||
|         <ai-search-bar> | ||||
|           <template slot="left"> | ||||
|             <el-button type="primary" icon="iconfont iconAdd" size="small" @click="add">添加</el-button> | ||||
|           </template> | ||||
|  | ||||
|           <template slot="right"> | ||||
|             <el-input v-model="search.title" size="small" placeholder="搜索标题" clearable | ||||
|                       v-throttle="() => {page.current = 1, getList()}" | ||||
|                       @clear=";(page.current = 1), (search.title = ''), getList()" suffix-icon="iconfont iconSearch"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|  | ||||
|         <ai-table :tableData="tableData" :colConfigs="colConfigs" :total="page.total" :current.sync="page.current" | ||||
|                   :size.sync="page.size" @getList="getList" class="ai-table"> | ||||
|           <!-- 首页封面 --> | ||||
|           <el-table-column label="首页封面" align="left" width="150" slot="imgUrl"> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <img :src="row.imgUrl" alt="" class="banner-img" v-if="row.imgUrl"/> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|  | ||||
|           <!-- 操作 --> | ||||
|           <el-table-column label="操作" align="center" width="300" slot="option"> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <el-button type="text" @click="release(row)" v-if="row.status == 1">取消发布</el-button> | ||||
|               <el-button type="text" @click="release(row)" v-else>发布</el-button> | ||||
|  | ||||
|               <el-button type="text" @click="detail(row)">详情</el-button> | ||||
|               <el-button type="text" @click="edit(row)">编辑</el-button> | ||||
|               <el-button type="text" @click="remove(row.id)">删除</el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|  | ||||
|     <!-- 添加的模态框 --> | ||||
|     <ai-dialog :title="dialog.title" :visible.sync="visible" @onCancel="visible = false" @onConfirm="addConfirm" | ||||
|                width="800px"> | ||||
|       <el-form ref="ruleForm" :model="dialogInfo" :rules="formRules" size="small" label-width="100px"> | ||||
|         <!-- 首页封面 --> | ||||
|         <el-form-item label="首页封面" prop="imgUrl"> | ||||
|           <ai-uploader v-model="dialogInfo.imgUrl" @change="change" :instance="instance" :limit="1"></ai-uploader> | ||||
|         </el-form-item> | ||||
|         <!-- 活动名称 --> | ||||
|         <el-form-item label="标题" prop="title"> | ||||
|           <el-input placeholder="请输入标题" :maxlength="30" show-word-limit v-model="dialogInfo.title"></el-input> | ||||
|         </el-form-item> | ||||
|         <!-- 连接类型 --> | ||||
|         <el-form-item label="链接类型" prop="type"> | ||||
|           <ai-select v-model="dialogInfo.type" placeholder="请选择链接类型" | ||||
|                      :selectList="$dict.getDict('bannerType')"></ai-select> | ||||
|         </el-form-item> | ||||
|         <!-- 链接 --> | ||||
|         <el-form-item label="链接" prop="linkUrl"> | ||||
|           <el-input placeholder="请输入链接" v-model="dialogInfo.linkUrl"></el-input> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|  | ||||
|     <!-- 详情的模态框 --> | ||||
|     <ai-dialog title="详情" :visible.sync="detailDialog" customFooter width="800px"> | ||||
|       <!--  --> | ||||
|       <el-form ref="ruleForm" :model="dialogInfo" :rules="formRules" size="small" label-width="100px"> | ||||
|         <ai-wrapper label-width="80px" :columnsNumber="1"> | ||||
|           <ai-info-item label="首页封面"> | ||||
|             <span><img :src="dialogInfo.imgUrl" alt="" style="width:100px;height:100px;"/></span> | ||||
|           </ai-info-item> | ||||
|           <ai-info-item label="标题"> | ||||
|             <span>{{ dialogInfo.title }}</span> | ||||
|           </ai-info-item> | ||||
|           <ai-info-item label="链接类型"> | ||||
|             <span>{{ this.dict.getLabel('bannerType', dialogInfo.type) }}</span> | ||||
|           </ai-info-item> | ||||
|           <ai-info-item label="链接"> | ||||
|             <span>{{ dialogInfo.linkUrl }}</span> | ||||
|           </ai-info-item> | ||||
|         </ai-wrapper> | ||||
|       </el-form> | ||||
|  | ||||
|       <div class="dialog-footer" slot="footer"> | ||||
|         <el-button @click="detailDialog=false">关闭</el-button> | ||||
|       </div> | ||||
|     </ai-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   label: '轮播图片', | ||||
|   name: 'AppCarousel', | ||||
|   // 组件 | ||||
|   components: {}, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       visible: false, | ||||
|       detailDialog: false, | ||||
|       // status: 0, | ||||
|       // id:'', | ||||
|       search: { | ||||
|         title: '', | ||||
|       }, | ||||
|       tableData: [], | ||||
|       page: { | ||||
|         size: 10, | ||||
|         current: 1, | ||||
|         total: 0, | ||||
|       }, | ||||
|       dialog: { | ||||
|         // title: '', | ||||
|         visible: false, | ||||
|       }, | ||||
|       dialogInfo: { | ||||
|         id: '', | ||||
|         title: '', | ||||
|         imgUrl: [], | ||||
|         type: '', | ||||
|         linkUrl: '', | ||||
|       }, | ||||
|       // fileList: '', | ||||
|       formRules: { | ||||
|         imgUrl: [{required: true, message: '请添加图片', trigger: 'blur'}], | ||||
|         title: [{required: true, message: '请输入标题', trigger: 'blur'}], | ||||
|         type: [{required: true, trigger: 'change', message: '请选择链接类型'}], | ||||
|         // linkUrl: [{ required: true, message: '请输入链接', trigger: 'blur' }] | ||||
|       }, | ||||
|       colConfigs: [ | ||||
|         {prop: 'imgUrl', label: '首页封面', slot: 'imgUrl'}, | ||||
|         { | ||||
|           prop: 'title', | ||||
|           label: '标题', | ||||
|  | ||||
|           'show-overflow-tooltip': true, | ||||
|         }, | ||||
|         { | ||||
|           prop: 'type', | ||||
|           label: '链接类型', | ||||
|           render: (h, {row}) => { | ||||
|             return h('span', null, this.dict.getLabel('bannerType', row.type)) | ||||
|           }, | ||||
|         }, | ||||
|         { | ||||
|           prop: 'status', | ||||
|           label: '发布状态', | ||||
|           width: 400, | ||||
|           render: (h, {row}) => { | ||||
|             return h('span', null, this.dict.getLabel('bannerSstatus', row.status)) | ||||
|           }, | ||||
|         }, | ||||
|  | ||||
|         {slot: 'option', label: '操作', width: 280}, | ||||
|       ], | ||||
|     } | ||||
|   }, | ||||
|   // 计算 | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|   }, | ||||
|   // 监听 | ||||
|   watch: {}, | ||||
|   // 实例创建后 | ||||
|   created() { | ||||
|     this.dict.load('bannerType', 'bannerSstatus').then(() => { | ||||
|       this.getList() | ||||
|     }) | ||||
|     // this.getList() | ||||
|     this.getShopList() | ||||
|   }, | ||||
|   // 实例渲染后 | ||||
|   mounted() { | ||||
|   }, | ||||
|   // 方法 | ||||
|   methods: { | ||||
|     getList() { | ||||
|       this.instance | ||||
|       .post(`/app/appbanner/list`, null, { | ||||
|         params: { | ||||
|           ...this.search, | ||||
|           ...this.page, | ||||
|         }, | ||||
|       }) | ||||
|       .then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           // console.log(res.data.records) | ||||
|           this.tableData = res.data.records | ||||
|  | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|       .catch(() => { | ||||
|       }) | ||||
|     }, | ||||
|     getShopList() { | ||||
|     }, | ||||
|     add() { | ||||
|       this.dialog.title = '添加' | ||||
|       this.dialogInfo = {} | ||||
|       this.getList() | ||||
|       this.visible = true | ||||
|     }, | ||||
|  | ||||
|     data(e) { | ||||
|       this.files.push(e) | ||||
|     }, | ||||
|     change(e) { | ||||
|       this.files = e | ||||
|     }, | ||||
|     // 确定新增 | ||||
|     addConfirm() { | ||||
|       // console.log('确定') | ||||
|       this.$refs.ruleForm.validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.instance.post(`/app/appbanner/addOrUpdate`, { | ||||
|             imgUrl: this.dialogInfo.imgUrl[0].url, | ||||
|             linkUrl: this.dialogInfo.linkUrl, | ||||
|             status: this.status, | ||||
|             title: this.dialogInfo.title, | ||||
|             type: this.dialogInfo.type, | ||||
|             id: this.dialogInfo.id, | ||||
|           }).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success('新增成功') | ||||
|               this.visible = false | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     // 发布/取消发布 | ||||
|     release(row) { | ||||
|       this.$confirm('确定此操作?').then(() => { | ||||
|         var status = row.status == 1 ? '0' : '1' | ||||
|         this.instance.post(`/app/appbanner/setStatus?id=${row.id}&status=${status}`) | ||||
|         .then((res) => { | ||||
|           if (res?.code == 0) { | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|     // 详情 | ||||
|     detail(row) { | ||||
|       this.detailDialog = true | ||||
|       this.instance.post(`/app/appbanner/detail?id=${row.id}`, { | ||||
|         // imgUrl: this.dialogInfo.imgUrl[0].url | ||||
|       }) | ||||
|       .then((res) => { | ||||
|         if (res?.data) { | ||||
|           this.dialogInfo = {...row} | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     // 编辑 | ||||
|     edit(row) { | ||||
|       this.dialog.title = '编辑' | ||||
|       this.visible = true | ||||
|       this.dialogInfo = {...row} | ||||
|       this.dialogInfo.imgUrl = [{url: ''}] | ||||
|       this.dialogInfo.imgUrl[0].url = row.imgUrl | ||||
|       // console.log(this.dialogInfo) | ||||
|     }, | ||||
|     // 删除 | ||||
|     remove(id) { | ||||
|       this.$confirm('删除后不可恢复,是否要删除该事项?', { | ||||
|         type: 'error', | ||||
|       }).then(() => { | ||||
|         this.instance.post(`/app/appbanner/delete?ids=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('删除成功!') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .appcarousel { | ||||
|   height: 100%; | ||||
|   // padding: 15px 10px; | ||||
|   .banner-img { | ||||
|     width: 50px; | ||||
|     height: 50px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										71
									
								
								packages/extra/AppCodeGeneration/AppCodeGeneration.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								packages/extra/AppCodeGeneration/AppCodeGeneration.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| <template> | ||||
|   <component | ||||
|     v-if="hasApp && configLoaded" | ||||
|     :is="componentName" | ||||
|     :params="params" | ||||
|     :backType="backType" | ||||
|     :instance="instance" | ||||
|     :dict="dict" | ||||
|     :appType="appType" | ||||
|     :appId="appId" | ||||
|     :configs="configs" | ||||
|     @change="changePage" /> | ||||
|   <ai-empty v-else-if="hasApp">应用配置加载中...</ai-empty> | ||||
|   <ai-empty v-else>读取应用失败</ai-empty> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import Add from './components/Add.vue' | ||||
|   import Detail from './components/Detail.vue' | ||||
|   import List from './components/List.vue' | ||||
|  | ||||
|   export default { | ||||
|     label: '代码生成', | ||||
|     name: 'AppCodeGeneration', | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|     components: {Add, Detail, List}, | ||||
|     computed: { | ||||
|       appId() { | ||||
|         return this.$route.query.app | ||||
|       }, | ||||
|       hasApp() { | ||||
|         return !!this.appId | ||||
|       }, | ||||
|       configLoaded() { | ||||
|         return !!this.configs.id | ||||
|       } | ||||
|     }, | ||||
|     data() { | ||||
|       return { | ||||
|         componentName: 'list', | ||||
|         params: {}, | ||||
|         backType: '', | ||||
|         configs: {}, | ||||
|         appType: '' | ||||
|       } | ||||
|     }, | ||||
|     methods: { | ||||
|       changePage(data) { | ||||
|         this.componentName = data.type | ||||
|         this.params = data.params | ||||
|         this.backType = data.backType || '' | ||||
|       }, | ||||
|       getConfigs() { | ||||
|         this.instance.post(`/app/appapplicationinfo/queryApplicationInfo`, null, { | ||||
|           params: {appId: this.appId} | ||||
|         }).then((res) => { | ||||
|           if (res?.data) { | ||||
|             this.appType = res.data.appType | ||||
|             this.configs = res.data | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|     created() { | ||||
|       this.getConfigs() | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
							
								
								
									
										230
									
								
								packages/extra/AppCodeGeneration/app/visit/Visit.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								packages/extra/AppCodeGeneration/app/visit/Visit.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | ||||
| <template> | ||||
|   <ai-card title="走访记录" class="visit" v-loading="loading"> | ||||
|     <el-button slot="right" icon="iconfont iconAdd" type="text" @click="isShow = true">添加走访记录</el-button> | ||||
|     <template #content> | ||||
|       <div class="visit-list"> | ||||
|         <div class="visit-item" v-for="(item, index) in list" :key="index"> | ||||
|           <div class="visit-item__top"> | ||||
|             <div class="left"> | ||||
|               <div class="avatar">{{ item.name.substr(item.name.length - 2) }}</div> | ||||
|               <h2>{{ item.name }}</h2> | ||||
|             </div> | ||||
|             <span>{{ item.visitTime }}</span> | ||||
|           </div> | ||||
|           <b>{{ item.title }}</b> | ||||
|           <p>{{ item.description }}</p> | ||||
|           <div class="visit-imgs" v-if="item.images.length"> | ||||
|             <ai-uploader v-model="item.images" :instance="instance" :limit="9" disabled/> | ||||
|           </div> | ||||
|           <div class="visit-status"> | ||||
|             <span>现实状态:</span> | ||||
|             <i>{{ dict.getLabel('visitCondolenceReality', item.reality) }}</i> | ||||
|           </div> | ||||
|         </div> | ||||
|         <ai-empty v-if="!list.length"></ai-empty> | ||||
|       </div> | ||||
|       <ai-dialog | ||||
|           :visible.sync="isShow" | ||||
|           width="1000px" | ||||
|           height="500px" | ||||
|           title="添加走访记录" | ||||
|           @close="onClose" | ||||
|           @onConfirm="onConfirm"> | ||||
|         <el-form ref="form" :model="form" label-width="110px" label-position="right" size="small"> | ||||
|           <ai-bar title="走访记录"></ai-bar> | ||||
|           <div class="ai-form" :model="form" label-width="110px" label-position="right"> | ||||
|             <el-form-item label="走访时间" prop="visitTime" | ||||
|                           :rules="[{ required: true, message: '请选择走访时间', trigger: 'change' }]"> | ||||
|               <el-date-picker | ||||
|                   v-model="form.visitTime" | ||||
|                   type="datetime" | ||||
|                   style="width: 100%;" | ||||
|                   value-format="yyyy-MM-dd HH:mm:ss" | ||||
|                   placeholder="请选择走访时间"> | ||||
|               </el-date-picker> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="现实状态" prop="reality" | ||||
|                           :rules="[{ required: true, message: '请选择现实状态', trigger: 'change' }]"> | ||||
|               <ai-select | ||||
|                   v-model="form.reality" | ||||
|                   :selectList="dict.getDict('visitCondolenceReality')" | ||||
|                   laceholder="请选择现实状态"> | ||||
|               </ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="入户走访事项" prop="title" style="width: 100%;" | ||||
|                           :rules="[{ required: true, message: '请输入 入户走访事项'}]"> | ||||
|               <el-input placeholder="请输入 入户走访事项" v-model="form.title" maxlength="30" show-word-limit/> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="入户走访内容" prop="description" style="width: 100%;"> | ||||
|               <el-input type="textarea" placeholder="请输入 入户走访内容" v-model="form.description" :rows="4" maxlength="500" | ||||
|                         show-word-limit/> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="图片" prop="images" style="width: 100%;"> | ||||
|               <ai-uploader v-model="form.images" :instance="instance" :limit="9" isShowTip/> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-card> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'visit', | ||||
|  | ||||
|   props: ['id', 'dict', 'instance', 'appId', 'name', 'areaId'], | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       appList: [], | ||||
|       list: [], | ||||
|       loading: false, | ||||
|       isShow: false, | ||||
|       form: { | ||||
|         visitTime: '', | ||||
|         reality: '', | ||||
|         images: [], | ||||
|         description: '' | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']) | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     this.dict.load('visitCondolenceReality').then(() => { | ||||
|       this.getList() | ||||
|     }) | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getList() { | ||||
|       this.loading = true | ||||
|       this.instance.post(`/app/appvisitvondolence/list?optionId=${this.id}&size=10000`).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           this.list = res.data.records.map(item => { | ||||
|             return { | ||||
|               ...item, | ||||
|               images: item.images ? JSON.parse(item.images) : [] | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|  | ||||
|         this.loading = false | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onConfirm() { | ||||
|       this.$refs.form.validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.instance.post(`/app/appvisitvondolence/addOrUpdate`, { | ||||
|             ...this.form, | ||||
|             optionId: this.id, | ||||
|             images: JSON.stringify(this.form.images), | ||||
|             applicationId: this.appId, | ||||
|             name: this.name, | ||||
|             areaId: this.areaId | ||||
|           }).then(res => { | ||||
|             if (res.code === 0) { | ||||
|               this.$message.success('添加成功') | ||||
|               this.isShow = false | ||||
|  | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onClose() { | ||||
|       this.form = {} | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .visit { | ||||
|   .visit-list { | ||||
|     .visit-item { | ||||
|       padding: 10px 0; | ||||
|       border-bottom: 1px solid #eee; | ||||
|  | ||||
|       &:first-child { | ||||
|         padding-top: 0; | ||||
|       } | ||||
|  | ||||
|       &:last-child { | ||||
|         border-bottom: none; | ||||
|       } | ||||
|  | ||||
|       .visit-status { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         font-size: 14px; | ||||
|  | ||||
|         span { | ||||
|           color: #333; | ||||
|         } | ||||
|  | ||||
|         i { | ||||
|           color: #999; | ||||
|           font-style: normal; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       & > p { | ||||
|         line-height: 1.4; | ||||
|         margin-bottom: 4px; | ||||
|         text-align: justify; | ||||
|         color: #666; | ||||
|         font-size: 16px; | ||||
|       } | ||||
|  | ||||
|       b { | ||||
|         display: block; | ||||
|         margin-bottom: 6px; | ||||
|       } | ||||
|  | ||||
|       .visit-item__top { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         justify-content: space-between; | ||||
|         margin-bottom: 10px; | ||||
|  | ||||
|         span { | ||||
|           font-size: 14px; | ||||
|           color: #999; | ||||
|         } | ||||
|  | ||||
|         .left { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|  | ||||
|           img, .avatar { | ||||
|             width: 40px; | ||||
|             height: 40px; | ||||
|             line-height: 40px; | ||||
|             text-align: center; | ||||
|             margin-right: 10px; | ||||
|             border-radius: 50%; | ||||
|             font-size: 14px; | ||||
|             color: #fff; | ||||
|             background: #26f; | ||||
|           } | ||||
|  | ||||
|           h2 { | ||||
|             font-size: 16px; | ||||
|             font-weight: 500; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										533
									
								
								packages/extra/AppCodeGeneration/components/Add.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										533
									
								
								packages/extra/AppCodeGeneration/components/Add.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,533 @@ | ||||
| <template> | ||||
|   <ai-detail v-if="pageShow" class="add-form"> | ||||
|     <template #title> | ||||
|       <ai-title :title="params.id ? '编辑'+colData.applicationName : '新增' + colData.applicationName" isShowBottomBorder | ||||
|                 isShowBack @onBackClick="onBack(true)"></ai-title> | ||||
|     </template> | ||||
|     <template #content> | ||||
|       <el-form ref="formData" class="ai-form" :rules="rules" :model="formData" label-width="110px" size="small"> | ||||
|         <ai-card :title="items[0].groupName" v-for="(items, indexs) in formDataList" :key="indexs" v-if="items.length"> | ||||
|           <template slot="content"> | ||||
|             <div v-for="(item, index) in items" :key="index" :style="item.grid == 1 ? 'width: 100%;' : 'width: 50%;'" | ||||
|                  class="form-div"> | ||||
|               <el-form-item :label="item.fieldName" :prop="item.fieldDbName" style="width: 100%"> | ||||
|                 <!-- 字典下拉选择 --> | ||||
|                 <template v-if="item.type == 'dict'"> | ||||
|                   <ai-select v-model="formData[item.fieldDbName]" :placeholder="item.fieldName" :selectList="dict.getDict(item.dict)" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" /> | ||||
|                 </template> | ||||
|                 <!-- 单选radio --> | ||||
|                 <template v-else-if="item.type == 'radio'"> | ||||
|                   <el-radio-group v-model="formData[item.fieldDbName]" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"> | ||||
|                     <el-radio :label="item.dictValue" v-for="(item, i) in dict.getDict(item.dict)" :key="i">{{ item.dictName }}</el-radio> | ||||
|                   </el-radio-group> | ||||
|                 </template> | ||||
|                 <!-- 开关onOff --> | ||||
|                 <template v-else-if="item.type == 'onOff'"> | ||||
|                   <el-switch v-model="formData[item.fieldDbName]" active-color="#26f" inactive-color="#ddd" active-value="1" inactive-value="0" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"></el-switch> | ||||
|                 </template> | ||||
|                 <!-- 多选checkbox --> | ||||
|                 <template v-else-if="item.type == 'checkbox'"> | ||||
|                   <el-checkbox-group v-model="formData[item.fieldDbName]" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"> | ||||
|                     <el-checkbox v-for="(item, i) in dict.getDict(item.dict)" :label="item.dictValue" :key="i"> | ||||
|                       {{ item.dictName }} | ||||
|                     </el-checkbox> | ||||
|                   </el-checkbox-group> | ||||
|                 </template> | ||||
|                 <!-- 网格 --> | ||||
|                 <template v-else-if="item.type === 'gird'"> | ||||
|                   <el-input disabled :value="girdName" size="small" placeholder="请选择网格"> | ||||
|                     <template slot="append"> | ||||
|                       <el-button size="small" @click="showGrid = true, treeObj.checkedKeys = formData[item.fieldDbName] ? [formData[item.fieldDbName]] : [], gridFieldName = item.fieldDbName">选择网格</el-button> | ||||
|                     </template> | ||||
|                   </el-input> | ||||
|                 </template> | ||||
|                 <template v-else-if="item.type === 'resident'"> | ||||
|                   <el-input | ||||
|                     v-model="formData.name" | ||||
|                     :placeholder="'请选择'+item.fieldName"> | ||||
|                     <template slot="append"> | ||||
|                       <ai-person-select | ||||
|                         :instance="instance" | ||||
|                         :disabled="!!params.id" | ||||
|                         :url="'/app/appresident/list?auditType=1&areaId=' + user.info.areaId" | ||||
|                         :isMultiple="false" dialogTitle="选择" @selectPerson="onChange"> | ||||
|                         <template name="option" v-slot:option="{ item }"> | ||||
|                           <span class="iconfont iconProlife">{{ item.name }}</span> | ||||
|                           <ai-id mode="show" :show-eyes="false" :value="item.idNumber"/> | ||||
|                         </template> | ||||
|                       </ai-person-select> | ||||
|                     </template> | ||||
|                   </el-input> | ||||
|                 </template> | ||||
|                 <template v-else-if="item.type == 'idNumber'"> | ||||
|                   <ai-id v-model="formData[item.fieldDbName]" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" /> | ||||
|                 </template> | ||||
|                 <!-- input输入框 --> | ||||
|                 <template v-else-if="item.type == 'input' || item.type == 'name' || item.type == 'phone'"> | ||||
|                   <el-input v-model="formData[item.fieldDbName]" :placeholder="'请输入'+item.fieldName" clearable :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" | ||||
|                             :maxlength="item.maxLength" show-word-limit></el-input> | ||||
|                 </template> | ||||
|                 <!-- number 输入框 --> | ||||
|                 <template v-else-if="item.type == 'number'"> | ||||
|                   <el-input-number v-model="formData[item.fieldDbName]" :label="'请输入'+item.fieldName" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" :precision="item.decimalPlaces" :max="item.maxValue" :min="item.minValue"></el-input-number> | ||||
|                 </template> | ||||
|                 <!-- textarea输入框 --> | ||||
|                 <template v-else-if="item.type == 'textarea' || item.type == 'text'"> | ||||
|                   <el-input v-model="formData[item.fieldDbName]" :placeholder="'请输入'+item.fieldName" clearable :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" | ||||
|                             :maxlength="item.maxLength" type="textarea" show-word-limit :rows="3"></el-input> | ||||
|                 </template> | ||||
|                 <!-- 日期选择 --> | ||||
|                 <template v-else-if="item.type == 'date'"> | ||||
|                   <el-date-picker style="width: 100%;" v-model="formData[item.fieldDbName]" type="date" placeholder="请选择" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" | ||||
|                                   :value-format="item.timePattern"></el-date-picker> | ||||
|                 </template> | ||||
|                 <!-- 日期带时分秒选择 --> | ||||
|                 <template v-else-if="item.type == 'datetime'"> | ||||
|                   <el-date-picker v-model="formData[item.fieldDbName]" type="datetime" placeholder="选择日期时间" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" | ||||
|                                   :value-format="item.timePattern"></el-date-picker> | ||||
|                 </template> | ||||
|                 <!-- 时间-时分秒选择 --> | ||||
|                 <template v-else-if="item.type == 'time'"> | ||||
|                   <el-time-picker v-model="formData[item.fieldDbName]" placeholder="请选择" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" | ||||
|                                   :value-format="item.timePattern"></el-time-picker> | ||||
|                 </template> | ||||
|                 <!-- 附件 --> | ||||
|                 <template v-else-if="item.type == 'upload'"> | ||||
|                   <ai-uploader :instance="instance" isShowTip fileType="file" v-model="formData[item.fieldDbName]" :disabled="item.disable == 1" | ||||
|                                acceptType=".zip,.rar,.doc,.docx,.xls,.ppt,.pptx,.pdf,.txt,.jpg,.png,.xlsx" | ||||
|                                :limit="item.fileMaxCount" :maxSize="item.fileChoseSize"></ai-uploader> | ||||
|                 </template> | ||||
|                 <!-- 富文本 --> | ||||
|                 <template v-else-if="item.type == 'rtf'"> | ||||
|                   <ai-editor v-model="formData[item.fieldDbName]" :instance="instance" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"/> | ||||
|                 </template> | ||||
|                 <!-- 地区选择 --> | ||||
|                 <template v-else-if="item.type == 'area'"> | ||||
|                   <ai-area-get :instance="instance" v-model="formData[item.fieldDbName]" :name.sync="formData[item.fieldDbName +'_name']" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"/> | ||||
|                 </template> | ||||
|                 <!-- 人员选择 --> | ||||
|                 <div class="especial" v-else-if="item.type == 'user'"> | ||||
|                   <span class="icon"> </span> | ||||
|                   <span class="people">{{ item.fieldName }}:</span> | ||||
|                   <ai-wechat-selecter slot="append" isShowUser :instance="instance" | ||||
|                                       v-model="formData[item.fieldDbName]"></ai-wechat-selecter> | ||||
|                 </div> | ||||
|               </el-form-item> | ||||
|             </div> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </el-form> | ||||
|       <ai-dialog | ||||
|         title="选择网格" | ||||
|         :visible.sync="showGrid" | ||||
|         :destroyOnClose="true" | ||||
|         @close="showGrid = false" | ||||
|         @onConfirm="getCheckedTree" | ||||
|         width="720px"> | ||||
|         <div class="grid"> | ||||
|           <el-tree | ||||
|             :data="treeObj.treeList" | ||||
|             :props="treeObj.defaultProps" | ||||
|             node-key="id" | ||||
|             ref="tree" | ||||
|             :check-strictly="true" | ||||
|             show-checkbox | ||||
|             :default-checked-keys="treeObj.checkedKeys" | ||||
|             default-expand-all | ||||
|             @check="onCheckChange"> | ||||
|           </el-tree> | ||||
|         </div> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button class="delete-btn footer-btn" @click="onBack">取消</el-button> | ||||
|       <el-button class="footer-btn" type="primary" :loading="isLoading" @click="submit('formData')">提交</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'Add', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     params: Object, | ||||
|     dict: Object, | ||||
|     appId: String, | ||||
|     backType: String, | ||||
|     configs: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       formData: { | ||||
|         age: 2 | ||||
|       }, | ||||
|       pickerOptions0: { | ||||
|         disabledDate(time) { | ||||
|           return time.getTime() < Date.now() - 8.64e7; | ||||
|         } | ||||
|       }, | ||||
|       isLoading: false, | ||||
|       girdName: '', | ||||
|       gridFieldName: '', | ||||
|       showGrid: false, | ||||
|       formDataList: [], | ||||
|       pageShow: true, | ||||
|       treeObj: { | ||||
|         treeList: [], | ||||
|         defaultProps: { | ||||
|           children: "girdList", | ||||
|           label: "girdName", | ||||
|         }, | ||||
|         checkedKeys: [], | ||||
|       }, | ||||
|       colData: {}, | ||||
|       areaId: '' | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     rules() { | ||||
|       let rules = {} | ||||
|       this.colData?.tableInfos?.map(e => { | ||||
|         rules[e.fieldDbName] = [] | ||||
|         if (e.mustFill == 1) {//是否必填 | ||||
|           rules[e.fieldDbName]?.push({required: true, message: e.fieldTips}) | ||||
|         } | ||||
|       }) | ||||
|       return rules | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getGridList() | ||||
|     this.getFormData() | ||||
|     if (this.params.id) { | ||||
|       this.getDetail() | ||||
|     }  | ||||
|   }, | ||||
|   methods: { | ||||
|     getGridList() { | ||||
|       this.instance.post(`/app/appgirdinfo/listAll`).then((res) => { | ||||
|         if (res.code == 0) { | ||||
|           this.treeObj.treeList = this.format(res.data) | ||||
|           if (this.formData.girdId) { | ||||
|             this.$set(this.treeObj, 'checkedKeys', [this.formData.girdId]) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onChange (e) { | ||||
|       this.formData.resident_id = e.id | ||||
|       Object.keys(this.formData).forEach(item => { | ||||
|         for (var p in e){ | ||||
|           if (item === p) { | ||||
|             this.$set(this.formData, item, e[item]) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
|       const idNumberInfo = this.idCardNoUtil.getIdCardInfo(e.idNumber) | ||||
|       this.$set(this.formData, 'birthDate', idNumberInfo.birthday) | ||||
|       this.formData.photo = e.photo ? [{ | ||||
|         url: e.photo | ||||
|       }] : [] | ||||
|     }, | ||||
|     getCheckedTree() { | ||||
|       const gird = this.$refs.tree.getCheckedNodes() | ||||
|  | ||||
|       if (gird.length) { | ||||
|         this.girdName = gird[0].girdName | ||||
|         this.formData[this.gridFieldName] = gird[0].id | ||||
|       } else { | ||||
|         this.girdName = '' | ||||
|         this.formData[this.gridFieldName] = '' | ||||
|       } | ||||
|  | ||||
|       this.showGrid = false | ||||
|     }, | ||||
|  | ||||
|     onCheckChange (e) { | ||||
|       this.$nextTick(() => { | ||||
|         this.$refs.tree.getCheckedKeys().forEach(v => { | ||||
|           this.$refs.tree.setChecked(v, false) | ||||
|         }) | ||||
|         this.$refs.tree.setChecked(e.id, true) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     format (list) { | ||||
|       return list.map(item => { | ||||
|         if (item.girdLevel !== '2') { | ||||
|           item.disabled = true | ||||
|         } | ||||
|  | ||||
|         if (item.girdList && item.girdList.length) { | ||||
|           item.girdList = this.format(item.girdList) | ||||
|         } | ||||
|  | ||||
|         return item | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     initForm(data) { | ||||
|       this.colData = data | ||||
|       let dictList = [] | ||||
|       let formList = {} | ||||
|       data.tableInfos.map((item) => { | ||||
|         let colItem | ||||
|         if (item.dictionaryCode) { | ||||
|           dictList.push(item.dictionaryCode) | ||||
|         } | ||||
|         if (item.dictionaryCode && item.type != 'radio' && item.type != 'checkbox' && item.type != 'onOff') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             type: 'dict', | ||||
|             dict: item.dictionaryCode | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = item.defaultValue || '' | ||||
|           } | ||||
|         } else if (item.type == 'radio') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             dict: item.dictionaryCode, | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = item.defaultValue || '' | ||||
|           } | ||||
|         } else if (item.type == 'checkbox') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             dict: item.dictionaryCode, | ||||
|             fieldValue: [] | ||||
|           } | ||||
|           if (!this.params.id && item.defaultValue) { | ||||
|             var val = item.defaultValue?.split('`') | ||||
|             colItem.fieldValue = val | ||||
|           } | ||||
|  | ||||
|         } else if (item.type === 'upload') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             fieldValue: [] | ||||
|           } | ||||
|         } else if (item.type == 'onOff') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = item.defaultValue || 0 | ||||
|           } | ||||
|         } else if (item.type == 'number') { | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             type: item.type, | ||||
|             min: item.minValue || 1, | ||||
|             max: item.maxValue || 1000000000, | ||||
|             minValue: item.minValue || 1, | ||||
|             maxValue: item.maxValue || 1000000000 | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = Number(item.defaultValue) || 0 | ||||
|           } | ||||
|         }else { | ||||
|           if (item.type == 'date' && !item.timePattern) { | ||||
|             item.timePattern = 'yyyy-MM-dd' | ||||
|           } | ||||
|           if (item.type == 'datetime' && !item.timePattern) { | ||||
|             item.timePattern = 'yyyy-MM-dd HH:mm:ss' | ||||
|           } | ||||
|           if (item.type == 'time' && !item.timePattern) { | ||||
|             item.timePattern = 'HH:mm:ss' | ||||
|           } | ||||
|  | ||||
|           colItem = { | ||||
|             ...item, | ||||
|             type: item.type, | ||||
|           } | ||||
|           if (!this.params.id) { | ||||
|             colItem.fieldValue = item.defaultValue || '' | ||||
|           } | ||||
|         } | ||||
|         // console.log(colItem) | ||||
|         formList[item.groupIndex]?.push(colItem) || (formList[item.groupIndex] = [colItem]) | ||||
|         if (item.type === 'number') { | ||||
|           this.$set(this.formData, item.fieldDbName, 1) | ||||
|         } else { | ||||
|           this.$set(this.formData, item.fieldDbName, colItem.fieldValue || '') | ||||
|         } | ||||
|       }) | ||||
|       this.formDataList = Object.values(formList) | ||||
|  | ||||
|       this.$forceUpdate() | ||||
|  | ||||
|       if (dictList.length) { | ||||
|         this.getDictList(dictList) | ||||
|       } else { | ||||
|         this.pageShow = true | ||||
|       } | ||||
|     }, | ||||
|     getFormData() { | ||||
|       this.initForm(this.configs) | ||||
|     }, | ||||
|     getDetail() { | ||||
|       this.instance.post(`/app/appapplicationinfo/queryDetailById?appId=${this.appId}&id=${this.params.id}`).then((res) => { | ||||
|         if (res?.data) { | ||||
|           this.configs.tableInfos.map((item) => { | ||||
|             this.formData[item.fieldDbName] = res.data[item.fieldDbName] || '' | ||||
|             if(item.type == 'checkbox') { | ||||
|               var checkList = this.formData[item.fieldDbName]?.split(',') | ||||
|               this.formData[item.fieldDbName] = checkList | ||||
|             } | ||||
|  | ||||
|             if (item.type === 'gird' && this.formData[item.fieldDbName]) { | ||||
|               this.girdName = res.data[`${item.fieldDbName}_name`] | ||||
|             } | ||||
|  | ||||
|             if (item.type === 'upload' && !this.formData[item.fieldDbName]) { | ||||
|               this.formData[item.fieldDbName] = [] | ||||
|             } | ||||
|  | ||||
|             if (item.type === 'upload' && this.formData[item.fieldDbName]) { | ||||
|               this.formData[item.fieldDbName] = this.formData[item.fieldDbName].split(',').map(v => { | ||||
|                 return { | ||||
|                   url: v | ||||
|                 } | ||||
|               }) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getDictList(listName) { | ||||
|       this.dict.load(listName.join(',')).then(() => { | ||||
|         this.pageShow = true | ||||
|       }) | ||||
|     }, | ||||
|     submit() { | ||||
|       this.$refs.formData?.validate((valid) => { | ||||
|         if (valid) { | ||||
|           this.isLoading = true | ||||
|           this.formDataList.map((item) => { | ||||
|             if (item.length) { | ||||
|               item.map((items) => { | ||||
|                 if (items.type == 'checkbox' && this.formData[items.fieldDbName].length) { //多选 | ||||
|                   this.formData[items.fieldDbName] = this.formData[items.fieldDbName]?.toString() | ||||
|                 } | ||||
|                 if (items.type == 'upload') { | ||||
|                   this.formData[items.fieldDbName] = this.formData[items.fieldDbName].map(v => v.url).join(',') | ||||
|                 } | ||||
|  | ||||
|                 if(items.type == 'gird' && this.formData[items.fieldDbName]) { | ||||
|                   this.formData[items.fieldDbName] = this.formData[items.fieldDbName] + '_' + this.girdName | ||||
|                 } | ||||
|                 if(items.type == 'area' && this.formData[items.fieldDbName]) { | ||||
|                   var area = [] | ||||
|                   area.push(this.formData[items.fieldDbName]) | ||||
|                   area.push(this.formData[items.fieldDbName+'_name']) | ||||
|                   this.formData[items.fieldDbName] = area.join('_') | ||||
|                 } | ||||
|               }) | ||||
|             } | ||||
|           }) | ||||
|           this.instance.post(`/app/appapplicationinfo/addOrUpdate?appId=${this.appId}`, { | ||||
|             ...this.formData, | ||||
|             id: this.params.id || '' | ||||
|           }).then((res) => { | ||||
|             this.isLoading = false | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('提交成功') | ||||
|               setTimeout(() => { | ||||
|                 this.onBack(true) | ||||
|               }, 600) | ||||
|             } | ||||
|           }).catch(() => { | ||||
|             this.isLoading = false | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     onBack(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: this.backType == 'Detail' ? 'detail' : 'list', | ||||
|         params: this.params, | ||||
|         isRefresh: !!isRefresh, | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| ::v-deep .ai-card{ | ||||
|   width: 100%; | ||||
| } | ||||
| .form-div { | ||||
|   display: inline-block; | ||||
|   vertical-align: top; | ||||
| } | ||||
|  | ||||
| .add-form { | ||||
|   ::v-deep .AiPersonSelect { | ||||
|     .el-button { | ||||
|       border-color: transparent; | ||||
|     background-color: transparent; | ||||
|     color: inherit; | ||||
|     border-top: 0; | ||||
|     border-bottom: 0; | ||||
|     background: transparent; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .especial { | ||||
|   margin-bottom: 12px; | ||||
|  | ||||
|   .icon { | ||||
|     vertical-align: top; | ||||
|     display: inline-block; | ||||
|     padding-top: 5px; | ||||
|     margin-left: 20px; | ||||
|     color: #f46; | ||||
|   } | ||||
|  | ||||
|   .people { | ||||
|     display: inline-block; | ||||
|     font-size: 14px; | ||||
|     color: #666; | ||||
|     padding-right: 12px; | ||||
|     vertical-align: top; | ||||
|     width: 64px; | ||||
|     word-break: break-all; | ||||
|     box-sizing: border-box; | ||||
|   } | ||||
|  | ||||
|   .AiWechatSelecter { | ||||
|     display: inline-block; | ||||
|     margin-left: 3px; | ||||
|   } | ||||
|  | ||||
|   .hint { | ||||
|     font-size: 14px; | ||||
|     color: #999; | ||||
|     margin-left: 16px; | ||||
|   } | ||||
|  | ||||
|   .mar-r40 { | ||||
|     margin-right: 40px; | ||||
|   } | ||||
|  | ||||
|   .w80 { | ||||
|     width: 80px; | ||||
|     text-align: right; | ||||
|     color: #888; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .AiWechatSelecter { | ||||
|   width: calc(100% - 120px); | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										257
									
								
								packages/extra/AppCodeGeneration/components/Detail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								packages/extra/AppCodeGeneration/components/Detail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,257 @@ | ||||
| <template> | ||||
|   <ai-detail v-loading="pageShow" isHasSidebar> | ||||
|     <template #title> | ||||
|       <ai-title :title="colData.applicationName+'详情'" isShowBottomBorder isShowBack @onBackClick="onBack(true)"></ai-title> | ||||
|     </template> | ||||
|     <template #content> | ||||
|       <AiSidebar :tabTitle="tabTitle" v-model="currIndex" v-if="appType"></AiSidebar> | ||||
|       <ai-card v-show="currIndex === 0" :title="items[0].groupName" v-for="(items, indexs) in formDataList" :key="indexs"> | ||||
|         <template slot="content"> | ||||
|           <ai-wrapper> | ||||
|             <ai-info-item :label="item.fieldName" v-show="item.type !== 'resident'" v-for="(item, index) in items" :key="index" :isLine="item.grid == 1"> | ||||
|               <span v-if="item.dict && item.type != 'checkbox'">{{$dict.getLabel(item.dict, formData[item.fieldDbName]) || '-'}}</span> | ||||
|               <span v-else-if="item.type == 'checkbox'">{{formData[item.fieldDbName]}}</span> | ||||
|               <span v-else-if="item.type == 'rtf'" v-html="formData[item.fieldDbName]"></span> | ||||
|               <ai-file-list :fileList="formData[item.fieldDbName]" v-else-if="item.type == 'upload'" :fileOps="{name: 'name', size: 'fileSizeStr'}"></ai-file-list> | ||||
|               <span v-else-if="item.type == 'area'">{{ formData[item.fieldDbName + '_name'] }}</span> | ||||
|               <span v-else-if="item.type == 'gird'">{{ formData[item.fieldDbName + '_name'] }}</span> | ||||
|               <span v-else>{{ formData[item.fieldDbName] || '-' }}</span> | ||||
|             </ai-info-item> | ||||
|           </ai-wrapper> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       <component | ||||
|         :is="component" | ||||
|         :name="params.name || params.name00" | ||||
|         :areaId="formData.area" | ||||
|         :id="params.id" | ||||
|         :appId="appId" | ||||
|         :dict="dict" | ||||
|         :instance="instance" | ||||
|         v-if="currIndex === 1"> | ||||
|       </component> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import { mapState } from 'vuex' | ||||
|   import Visit from '../app/visit/Visit' | ||||
|  | ||||
|   export default { | ||||
|     name: 'Detail', | ||||
|  | ||||
|     props: { | ||||
|       dict: Object, | ||||
|       appId: String, | ||||
|       params: Object, | ||||
|       configs: Object, | ||||
|       appType: String, | ||||
|       instance: Function | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       Visit | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         formData: {}, | ||||
|         colData: {}, | ||||
|         formDataList: [], | ||||
|         tabTitle: ['人员信息'], | ||||
|         pageShow: false, | ||||
|         currIndex: 0, | ||||
|         component: '' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       ...mapState(['user']), | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       if (!this.appType) return | ||||
|  | ||||
|       if (this.appType === '0') { | ||||
|         this.component = 'Visit' | ||||
|       } | ||||
|       this.dict.load('diyAppType').then(() => { | ||||
|         this.tabTitle.push(this.dict.getLabel('diyAppType', this.appType)) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.pageShow = true | ||||
|       this.getDetail() | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       initForm (data) { | ||||
|         this.colData = data | ||||
|         let dictList = [] | ||||
|         let formList = {} | ||||
|         data.tableInfos.map((item) => { | ||||
|           let colItem | ||||
|           if (item.dictionaryCode) { | ||||
|             dictList.push(item.dictionaryCode) | ||||
|           } | ||||
|           if (item.dictionaryCode && item.type != 'radio' && item.type != 'checkbox') { | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               type: 'dict', | ||||
|               dict: item.dictionaryCode | ||||
|             } | ||||
|           } else if (item.type == 'radio') { | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               dict: item.dictionaryCode, | ||||
|             } | ||||
|           } else if (item.type == 'checkbox') { | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               dict: item.dictionaryCode, | ||||
|               fieldValue: item.fieldValue?.split(',') || [] | ||||
|             } | ||||
|           } else if (item.type == 'onOff') { | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               fieldValue: 0 | ||||
|             } | ||||
|           } else { | ||||
|             if (item.type == 'date' && !item.timePattern) { | ||||
|               item.timePattern = 'yyyy-MM-dd' | ||||
|             } | ||||
|             if (item.type == 'datetime' && !item.timePattern) { | ||||
|               item.timePattern = 'HH:mm:ss yyyy-MM-dd' | ||||
|             } | ||||
|             if (item.type == 'time' && !item.timePattern) { | ||||
|               item.timePattern = 'HH:mm:ss' | ||||
|             } | ||||
|  | ||||
|             colItem = { | ||||
|               ...item, | ||||
|               type: item.type, | ||||
|             } | ||||
|           } | ||||
|           formList[item.groupIndex]?.push(colItem) || (formList[item.groupIndex] = [colItem]) | ||||
|           if (item.type === 'upload') { | ||||
|             this.$set(this.formData, colItem.fieldDbName, this.formData[colItem.fieldDbName] ? this.formData[colItem.fieldDbName].split(',').map(v => { | ||||
|               return { | ||||
|                 url: v | ||||
|               } | ||||
|             }) : []) | ||||
|           } else { | ||||
|             this.$set(this.formData, colItem.fieldDbName, this.formData[colItem.fieldDbName] || "") | ||||
|           } | ||||
|         }) | ||||
|         this.formDataList = Object.values(formList) | ||||
|  | ||||
|         this.$forceUpdate() | ||||
|  | ||||
|         if (dictList.length) { | ||||
|           this.getDictList(dictList) | ||||
|         } else { | ||||
|           this.pageShow = true | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       getFormData () { | ||||
|         this.initForm(this.configs) | ||||
|       }, | ||||
|  | ||||
|       getDetail () { | ||||
|         this.instance.post(`/app/appapplicationinfo/queryDetailById?appId=${this.appId}&id=${this.params.id}`).then((res) => { | ||||
|           if (res?.data) { | ||||
|             this.formData = res.data | ||||
|             this.getFormData() | ||||
|  | ||||
|             this.pageShow = false | ||||
|           } | ||||
|         }).catch(() => { | ||||
|           this.pageShow = false | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getDictList (listName) { | ||||
|         this.dict.load(listName.join(',')).then(() => { | ||||
|  | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onBack (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'list', | ||||
|           isRefresh: !!isRefresh, | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       toEdit () { | ||||
|         this.$emit('change', { | ||||
|           type: 'Add', | ||||
|           params: this.params, | ||||
|           backType: 'Detail' | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .form-div{ | ||||
|     display: inline-block; | ||||
|   } | ||||
|   .especial { | ||||
|     margin-bottom: 12px; | ||||
|     .icon { | ||||
|       vertical-align: top; | ||||
|       display: inline-block; | ||||
|       padding-top: 5px; | ||||
|       margin-left: 20px; | ||||
|       color: #f46; | ||||
|     } | ||||
|     .people { | ||||
|       display: inline-block; | ||||
|       font-size: 14px; | ||||
|       color: #666; | ||||
|       margin-right: 16px; | ||||
|       vertical-align: top; | ||||
|     } | ||||
|     .AiWechatSelecter { | ||||
|       display: inline-block; | ||||
|       margin-left: 3px; | ||||
|     } | ||||
|     .hint { | ||||
|       font-size: 14px; | ||||
|       color: #999; | ||||
|       margin-left: 16px; | ||||
|     } | ||||
|     .mar-r40{ | ||||
|       margin-right: 40px; | ||||
|     } | ||||
|     .w80{ | ||||
|       width: 80px; | ||||
|       text-align: right; | ||||
|       color: #888; | ||||
|     } | ||||
|   } | ||||
|   .add-icon{ | ||||
|     text-align: right; | ||||
|     cursor: pointer; | ||||
|     i{ | ||||
|       font-size: 14px; | ||||
|     } | ||||
|   } | ||||
|   .color1{ | ||||
|     color:#4B87FE; | ||||
|   } | ||||
|   .color2{ | ||||
|     color:#2EA222; | ||||
|   } | ||||
|   .color3{ | ||||
|     color:#999999; | ||||
|   } | ||||
|   .AiWechatSelecter{ | ||||
|     width: calc(100% - 150px); | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										305
									
								
								packages/extra/AppCodeGeneration/components/List.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								packages/extra/AppCodeGeneration/components/List.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,305 @@ | ||||
| <template> | ||||
|   <ai-list v-if="pageShow"> | ||||
|     <template slot="title"> | ||||
|       <ai-title :title="configs.applicationName" isShowBottomBorder></ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar v-if="searchList.length" bottomBorder style="margin-bottom: 12px;"> | ||||
|         <template #left> | ||||
|           <div v-for="(item, index) in searchList" :key="index"> | ||||
|             <ai-select | ||||
|               v-model="search[item.searchValue]" | ||||
|               :placeholder="'请选择'+item.label" clearable | ||||
|               @change="$forceUpdate();(page.current = 1), getList()" | ||||
|                        :selectList="dict.getDict(item.dict)" | ||||
|                        v-if="item.type == 'dict'"> | ||||
|             </ai-select> | ||||
|             <ai-search v-else-if="item.type == 'date'" :label="item.label"> | ||||
|               <el-date-picker size="small" v-model="search[item.searchValue]" type="daterange" range-separator="至" | ||||
|                               start-placeholder="开始日期" end-placeholder="结束日期" | ||||
|                               @change="$forceUpdate();(page.current = 1), getList()" | ||||
|                               value-format="yyyy-MM-dd"/> | ||||
|             </ai-search> | ||||
|             <ai-search v-else-if="item.type == 'time'" :label="item.label"> | ||||
|               <el-time-picker is-range size="small" v-model="search[item.searchValue]" range-separator="至" | ||||
|                               start-placeholder="开始时间" end-placeholder="结束时间" placeholder="选择时间范围" | ||||
|                               @change="$forceUpdate();(page.current = 1), getList()" | ||||
|                               value-format="HH:mm:ss"></el-time-picker> | ||||
|             </ai-search> | ||||
|             <ai-search v-else-if="item.type == 'area'" :label="item.label"> | ||||
|               <ai-area-get :instance="instance" v-model="search[item.searchValue]"/> | ||||
|             </ai-search> | ||||
|           </div> | ||||
|         </template> | ||||
|         <template #right v-if="showRightInput"> | ||||
|           <el-input :placeholder="placeholder" v-model="search.searchParam" size="small" | ||||
|                     @keyup.enter.native="$forceUpdate();(page.current = 1), getList()" | ||||
|                     @clear="$forceUpdate();(page.current = 1), getList()" | ||||
|                     @change="$forceUpdate();(page.current = 1), getList()" clearable prefix-icon="iconfont iconSearch"/> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-search-bar> | ||||
|         <template #left> | ||||
|           <el-button type="primary" icon="iconfont iconAdd" size="small" | ||||
|                      v-if="configs.insertEnable == 1" @click="toAdd('', 'Add')">添加 | ||||
|           </el-button> | ||||
|           <el-button icon="iconfont iconDelete" size="small" :disabled="ids.length == 0" | ||||
|                      v-if="configs.batchDelEnable == 1" @click="delAll()">删除 | ||||
|           </el-button> | ||||
|         </template> | ||||
|         <template #right> | ||||
|           <ai-import :instance="instance" v-if="configs.importEnable == 1" type="appapplicationinfo" | ||||
|                      :importParams="{appId}" :tplParams="{appId}" :name="configs.applicationName" @success="getList()"> | ||||
|             <el-button icon="iconfont iconImport">导入</el-button> | ||||
|           </ai-import> | ||||
|           <el-button icon="iconfont iconExported" size="small" v-if="configs.exportEnalbe == 1" @click="down()" | ||||
|                     >导出 | ||||
|           </el-button> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table class="ai-table" :tableData="tableData" :col-configs="colConfigs" :total="page.total" | ||||
|                 :current.sync="page.current" :size.sync="page.size" @getList="getList" :dict="dict" | ||||
|                 @selection-change="(v) => (ids = v.map((e) => e.id))"> | ||||
|         <el-table-column v-for="(item, indexs) in colConfigs" :key="indexs" :slot="item.slot" :label="item.label" | ||||
|                          show-overflow-tooltip | ||||
|                          align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div v-if="item.type != 'checkbox' && item.dict"> | ||||
|               {{ $dict.getLabel(item.dict, row[item.fieldDbName]) || '-' }} | ||||
|             </div> | ||||
|             <div v-if="item.type == 'rtf'" v-html="row[item.fieldDbName]"></div> | ||||
|             <div v-if="item.type == 'checkbox'">{{ row[item.fieldDbName] }}</div> | ||||
|             <div v-if="item.type == 'gird'">{{ row[item.fieldDbName + '_name'] }}</div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column slot="options" label="操作" fixed="right" align="center" width="160"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-options"> | ||||
|               <el-button type="text" @click="toDetail(row, 'Detail')">详情</el-button> | ||||
|               <el-button type="text" @click="toDetail(row, 'Add')" v-if="configs.editEnable == 1">编辑</el-button> | ||||
|               <el-button type="text" @click="del(row.id)" v-if="configs.deleteEnable == 1">删除</el-button> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: 'List', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     appId: String, | ||||
|     configs: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       pageShow: false, | ||||
|       tableData: [], | ||||
|       colConfigs: [], | ||||
|       page: { | ||||
|         size: 10, | ||||
|         current: 1, | ||||
|         total: 0, | ||||
|       }, | ||||
|       search: { | ||||
|         searchParam: '', | ||||
|       }, | ||||
|       searchList: [], | ||||
|       ids: [], | ||||
|       showRightInput: false, | ||||
|       placeholder: '请输入', | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.initConfigs() | ||||
|   }, | ||||
|   methods: { | ||||
|     initConfigs() { | ||||
|       var dictList = [] | ||||
|       var colList = [] | ||||
|       var searchList = [] | ||||
|       var placeholderList = [] | ||||
|       this.configs.showListFields.map((item) => { | ||||
|         var colItem | ||||
|         if (item.dictionaryCode) { | ||||
|           dictList.push(item.dictionaryCode) | ||||
|           colItem = { | ||||
|             slot: item.fieldDbName, | ||||
|             label: item.fieldName, | ||||
|             dict: item.dictionaryCode, | ||||
|             fieldDbName: item.fieldDbName, | ||||
|             type: item.type | ||||
|           } | ||||
|         } else if (item.type == 'rtf') { | ||||
|           colItem = {label: item.fieldName, type: item.type, slot: item.fieldDbName, fieldDbName: item.fieldDbName} | ||||
|         } else if (item.type == 'area') { | ||||
|           colItem = {prop: item.fieldDbName + '_name', label: item.fieldName, align: "center"} | ||||
|         } else { | ||||
|           colItem = {prop: item.fieldDbName, label: item.fieldName, align: "center"} | ||||
|         } | ||||
|         colList.push(colItem) | ||||
|       }) | ||||
|       this.configs.fuzzyQueryFields.map((item) => { | ||||
|         var searchItem = {} | ||||
|         if (item.dictionaryCode) { | ||||
|           searchItem = { | ||||
|             type: 'dict', | ||||
|             label: item.fieldName, | ||||
|             dict: item.dictionaryCode, | ||||
|             searchValue: item.fieldDbName | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (item.type == 'input' || item.type == 'name' || item.type == 'idNumber' || item.type == 'phone') { | ||||
|           placeholderList.push(item.fieldName) | ||||
|           this.showRightInput = true | ||||
|         } | ||||
|  | ||||
|         if (item.type == 'date') { | ||||
|           searchItem = { | ||||
|             type: 'date', | ||||
|             label: item.fieldName, | ||||
|             searchValue: item.fieldDbName | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (item.type == 'time') { | ||||
|           searchItem = { | ||||
|             type: 'time', | ||||
|             label: item.fieldName, | ||||
|             searchValue: item.fieldDbName | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (item.type == 'area') { | ||||
|           searchItem = { | ||||
|             type: 'area', | ||||
|             label: item.fieldName, | ||||
|             searchValue: item.fieldDbName | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         this.$set(this.search, item.fieldDbName, '') | ||||
|         searchList.push(searchItem) | ||||
|       }) | ||||
|  | ||||
|       this.colConfigs = colList | ||||
|       this.searchList = searchList | ||||
|       this.$forceUpdate() | ||||
|  | ||||
|       var text = placeholderList.join('/') | ||||
|       this.placeholder = this.placeholder + text | ||||
|  | ||||
|       if (this.configs.batchDelEnable == 1) { | ||||
|         this.colConfigs.unshift({type: 'selection', width: 100}) | ||||
|       } | ||||
|       if (dictList.length) { | ||||
|         this.getDictList(dictList) | ||||
|       } else { | ||||
|         this.pageShow = true | ||||
|         this.getList() | ||||
|       } | ||||
|     }, | ||||
|     getDictList(listName) { | ||||
|       this.dict.load(listName.join(',')).then(() => { | ||||
|         this.pageShow = true | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|     getList() { | ||||
|       this.instance.post(`/app/appapplicationinfo/list?appId=${this.appId}¤t=${this.page.current}&size=${this.page.size}`, {...this.search}).then((res) => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data.records | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     toDetail(item, type) { | ||||
|       this.$emit('change', { | ||||
|         type: type, | ||||
|         params: item, | ||||
|         backType: 'List' | ||||
|       }) | ||||
|     }, | ||||
|     toAdd() { | ||||
|       this.$emit('change', { | ||||
|         type: 'Add', | ||||
|         params: { | ||||
|           type: 'Add', | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     del(id) { | ||||
|       this.$confirm("删除后不可恢复,是否要删除?", { | ||||
|         type: 'error' | ||||
|       }).then(() => { | ||||
|         this.instance.post(`/app/appapplicationinfo/delete?appId=${this.appId}&ids=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success("删除成功!"); | ||||
|             this.getList(); | ||||
|           } | ||||
|         }) | ||||
|       }); | ||||
|     }, | ||||
|     delAll() { | ||||
|       if (this.ids.length > 100) { | ||||
|         return this.$message.error("删除的数据最多不能超过100条!"); | ||||
|       } | ||||
|       var id = this.ids.join(',') | ||||
|       this.del(id) | ||||
|     }, | ||||
|  | ||||
|     reset() { | ||||
|       Object.keys(this.search).forEach((e) => { | ||||
|         this.search[e] = '' | ||||
|       }) | ||||
|       this.getList() | ||||
|     }, | ||||
|     down() { | ||||
|       var id = '' | ||||
|       if (this.ids.length) { | ||||
|         id = this.ids.join(',') | ||||
|       } | ||||
|       this.instance.post(`/app/appapplicationinfo/export?appId=${this.appId}&ids=${id}`, this.search, { | ||||
|         responseType: 'blob', | ||||
|         timeout: 100000 | ||||
|       }).then(res => { | ||||
|         if (res?.type == "application/json") { | ||||
|           let reader = new FileReader() | ||||
|           reader.readAsText(res, "utf-8") | ||||
|           reader.onload = e => { | ||||
|             if (e.target.readyState === 2) { | ||||
|               let ret = JSON.parse(e.target.result) | ||||
|               if (ret?.code == 0) { | ||||
|                 this.$message.success(ret.msg) | ||||
|               } else this.$message.error(ret.msg) | ||||
|             } | ||||
|           } | ||||
|         } else { | ||||
|           const link = document.createElement('a') | ||||
|           let blob = new Blob([res], {type: res.type}) | ||||
|           link.style.display = 'none' | ||||
|           link.href = URL.createObjectURL(blob) | ||||
|           link.setAttribute('download', this.configs.applicationName + '.xls') | ||||
|           document.body.appendChild(link) | ||||
|           link.click() | ||||
|           document.body.removeChild(link) | ||||
|         } | ||||
|       }).catch((err) => { | ||||
|         this.$error.success(err) | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .mar-b10 { | ||||
|   margin-bottom: 10px; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										164
									
								
								packages/extra/AppLicence/AppLicence.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								packages/extra/AppLicence/AppLicence.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | ||||
| <template> | ||||
|   <section class="AppLicence"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="产品许可" isShowBottomBorder  :instance="instance"></ai-title> | ||||
|       <template #content> | ||||
|         <div class="licence-content"> | ||||
|           <img class="left-img" src="https://cdn.cunwuyun.cn/dvcp/key.png" alt="" /> | ||||
|           <div class="content-right"> | ||||
|             <h3 class="title">产品许可信息</h3> | ||||
|             <p class="mini-title">您当前的版本为Saas专业版,非常感谢您对我们产品的认可与支持!</p> | ||||
|             <div class="info"> | ||||
|               <span class="label">过期时间</span> | ||||
|               <span class="value color-f46" v-if="info.isExpired == 1">{{info.expireDate ? info.expireDate+'(已过期)' : '未激活'}}</span> | ||||
|               <span class="value color-26f" v-else>{{info.expireDate}}</span> | ||||
|             </div> | ||||
|             <div class="info"> | ||||
|               <span class="label">主板序列号</span> | ||||
|               <span class="value">{{info.mainBoard}}</span> | ||||
|             </div> | ||||
|             <div class="info"> | ||||
|               <span class="label">CPU</span> | ||||
|               <span class="value">{{info.cpu}}</span> | ||||
|             </div> | ||||
|             <div class="info"> | ||||
|               <span class="label">MAC地址</span> | ||||
|               <span class="value">{{info.mac}}</span> | ||||
|             </div> | ||||
|             <div class="info mar-b32"> | ||||
|               <span class="label">IP地址</span> | ||||
|               <span class="value">{{info.ip}}</span> | ||||
|             </div> | ||||
|             <el-upload | ||||
|               class="upload-demo" | ||||
|               action | ||||
|               multiple | ||||
|               accept=".lic" | ||||
|               :http-request="uploadFile"> | ||||
|               <div class="btn">上传许可</div> | ||||
|             </el-upload> | ||||
|           </div> | ||||
|         </div> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|   </section> | ||||
| </template> | ||||
| <script> | ||||
|  | ||||
| export default { | ||||
|   name: "AppLicence", | ||||
|   label: "产品许可", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       files: [], | ||||
|       info: {} | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.getDetail() | ||||
|   }, | ||||
|   methods: { | ||||
|     getDetail() { | ||||
|       this.instance.post(`/admin/license/detail`).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.info = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     uploadFile: function (file) { | ||||
|       let formData = new FormData(); | ||||
|       formData.append("file", file.file); | ||||
|       this.instance.post(`/admin/license/save`, formData, {withoutToken: false}).then(res => { | ||||
|         if (res && res.code == 0) { | ||||
|           this.$message.success("证书上传成功!"); | ||||
|           this.getDetail() | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
| }; | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
| .AppLicence { | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   ::v-deep .ai-list{ | ||||
|     background-color: #F5F6F9; | ||||
|   } | ||||
|   ::v-deep .ai-list .ai-list__content--right .ai-list__content--right-wrapper{ | ||||
|     background-color: #F5F6F9; | ||||
|     box-shadow: 0 0 0 0; | ||||
|     margin: 0!important; | ||||
|     padding: 0!important; | ||||
|   } | ||||
|   ::v-deep .el-upload-list{ | ||||
|     display: none; | ||||
|   } | ||||
|   .licence-content{ | ||||
|     display: flex; | ||||
|     margin-top: 30px; | ||||
|     .left-img{ | ||||
|       width: 200px; | ||||
|       height: 200px; | ||||
|     } | ||||
|     .content-right{ | ||||
|       width: 800px; | ||||
|       .title{ | ||||
|         font-size: 24px; | ||||
|         font-family: MicrosoftYaHei-Bold, MicrosoftYaHei; | ||||
|         font-weight: bold; | ||||
|         color: #222; | ||||
|         line-height: 24px; | ||||
|         margin-bottom: 8px; | ||||
|       } | ||||
|       .mini-title{ | ||||
|         font-size: 14px; | ||||
|         font-family: MicrosoftYaHei; | ||||
|         color: #555; | ||||
|         line-height: 22px; | ||||
|         margin-bottom: 20px; | ||||
|       } | ||||
|       .info{ | ||||
|         font-size: 14px; | ||||
|         font-family: MicrosoftYaHei; | ||||
|         line-height: 22px; | ||||
|         margin-bottom: 8px; | ||||
|         display: flex; | ||||
|         color: #222; | ||||
|         .label{ | ||||
|           width: 164px; | ||||
|         } | ||||
|         .value{ | ||||
|           width: calc(100% - 164px); | ||||
|         } | ||||
|         .color-26f{ | ||||
|           color: #26f; | ||||
|         } | ||||
|         .color-f46{ | ||||
|           color: #f46; | ||||
|         } | ||||
|       } | ||||
|       .mar-b32{ | ||||
|         margin-bottom: 32px; | ||||
|       } | ||||
|       .btn{ | ||||
|         width: 88px; | ||||
|         height: 32px; | ||||
|         line-height: 32px; | ||||
|         text-align: center; | ||||
|         background: linear-gradient(90deg, #299FFF 0%, #0C61FF 100%); | ||||
|         border-radius: 2px; | ||||
|         cursor: pointer; | ||||
|         color: #fff; | ||||
|         font-size: 14px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										40
									
								
								packages/extra/AppNavConfig/AppNavConfig.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								packages/extra/AppNavConfig/AppNavConfig.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <template> | ||||
|   <div class="AppShowProduce"> | ||||
|     <List | ||||
|       slot="content" | ||||
|       :instance="instance" | ||||
|       :dict="dict" | ||||
|       :permissions="permissions"> | ||||
|     </List> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import List from './components/List.vue' | ||||
|  | ||||
|   export default { | ||||
|     name: 'AppNavConfig', | ||||
|     label: '导航配置', | ||||
|  | ||||
|     components: { | ||||
|       List | ||||
|     }, | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .AppShowProduce { | ||||
|     height: 100%; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										515
									
								
								packages/extra/AppNavConfig/components/List.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										515
									
								
								packages/extra/AppNavConfig/components/List.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,515 @@ | ||||
| <template> | ||||
|   <ai-list class="list" v-loading="isLoading"> | ||||
|     <ai-title slot="title" title="导航配置" isShowBottomBorder></ai-title> | ||||
|     <template slot="content"> | ||||
|       <ai-card title="首页功能"> | ||||
|         <template #right> | ||||
|           <el-button size="small" type="primary" @click="eidt">{{ isEdit ? '退出编辑' : '编辑' }}</el-button> | ||||
|           <el-button size="small" @click="save" v-if="isEdit">保存</el-button> | ||||
|         </template> | ||||
|         <div slot="content" class="item-wrapper"> | ||||
|           <draggable | ||||
|             v-model="picked" | ||||
|             :animation="340" | ||||
|             group="select" | ||||
|             style="display: flex;" | ||||
|             handle=".mover"> | ||||
|             <div class="item" :class="[isEdit ? 'mover' : '']" v-for="(item, i) in picked" :key="i"> | ||||
|               <img :src="item.pictureUrl"> | ||||
|               <i class="el-icon-remove icon" @click="removeChoose(i)" v-if="isEdit"></i> | ||||
|               <h2>{{ item.name }}</h2> | ||||
|             </div> | ||||
|           </draggable> | ||||
|           <ai-empty style="width: 100%" v-if="!picked.length"></ai-empty> | ||||
|         </div> | ||||
|       </ai-card> | ||||
|       <ai-card title="全部功能"> | ||||
|         <template #right> | ||||
|           <el-button size="small" type="primary" @click="isShowAdd = true">新增应用</el-button> | ||||
|           <el-button size="small" type="danger" @click="isEdit = false, isRemove = !isRemove">{{ isRemove ? '取消删除' : '删除应用' }}</el-button> | ||||
|         </template> | ||||
|         <div class="all" slot="content"> | ||||
|           <div class="item-row" v-for="(group, index) in list" :key="index"> | ||||
|             <h2>{{ group.name }}</h2> | ||||
|             <div class="item-wrapper" v-if="isRest"> | ||||
|               <div class="item" v-for="(item, i) in group.list" :key="i"> | ||||
|                 <img :src="item.pictureUrl"> | ||||
|                 <i class="el-icon-error icon" @click="removeApp(item.id)" v-if="isRemove && item.type !== '0' && item.picked !== '1'"></i> | ||||
|                 <i class="el-icon-circle-plus icon" @click="addApp(item)" v-if="isCanAdd(item)"></i> | ||||
|                 <h2>{{ item.name }}</h2> | ||||
|                 <div class="item-setting"> | ||||
|                   <div class="item-mask"></div> | ||||
|                   <div class="item-wrapper__icon" @click.stop="editApp(item)"> | ||||
|                     <i class="el-icon-setting"></i> | ||||
|                     <div>编辑</div> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|           <ai-empty style="width: 100%" v-if="!list.length"></ai-empty> | ||||
|         </div> | ||||
|       </ai-card> | ||||
|       <ai-dialog | ||||
|         :visible.sync="isShowAdd" | ||||
|         width="780px" | ||||
|         height="580px" | ||||
|         :title="id ? '添加专题' : '编辑专题'" | ||||
|         @close="onClose" | ||||
|         @onConfirm="onConfirm"> | ||||
|         <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|           <div class="ai-form" :model="form" label-width="110px" label-position="right"> | ||||
|             <el-form-item label="应用名称" prop="name" style="width: 100%;" :rules="[{ required: true, message: '请输入应用名称', trigger: 'blur' }]"> | ||||
|               <el-input size="small" :maxlength="8" placeholder="请输入应用名称" v-model="form.name"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="应用模块" style="width: 100%;" prop="menuType" :rules="[{ required: true, message: '请选择应用模块', trigger: 'change' }]"> | ||||
|               <ai-select | ||||
|                 v-model="form.menuType" | ||||
|                 :selectList="dict.getDict('homeConfigMenuType')" | ||||
|                 @change="onChange" | ||||
|                 laceholder="请选择应用模块"> | ||||
|               </ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="认证类型" style="width: 100%;" prop="checkType"> | ||||
|               <ai-select | ||||
|                 v-model="form.checkType" | ||||
|                 :selectList="dict.getDict('miniConfigCheckType')" | ||||
|                 laceholder="请选择认证类型"> | ||||
|               </ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="应用类型" style="width: 100%;" prop="type" :rules="[{ required: true, message: '请选择应用类型', trigger: 'change' }]"> | ||||
|               <ai-select | ||||
|                 v-model="form.type" | ||||
|                 :selectList="typeDict" | ||||
|                 @change="onChange" | ||||
|                 laceholder="请选择应用类型"> | ||||
|               </ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="小程序appid" prop="appId" style="width: 100%;" v-if="form.type === '1'" :rules="[{ required: true, message: '请输入小程序appid', trigger: 'blur' }]"> | ||||
|               <el-input size="small" placeholder="请输入小程序appid" v-model="form.appId"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="链接" prop="url" style="width: 100%;" v-if="form.type === '2'" :rules="[{ required: true, message: '请输入链接', trigger: 'blur' }]"> | ||||
|               <el-input size="small" placeholder="请输入链接" v-model="form.url"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="小程序路径" prop="modulePath" style="width: 100%;" v-if="form.type === '3'" :rules="[{ required: true, message: '请输入小程序路径', trigger: 'blur' }]"> | ||||
|               <el-input size="small" placeholder="请输入小程序路径" v-model="form.modulePath"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="客服链接" prop="url" style="width: 100%;" v-if="form.type === '4'" :rules="[{ required: true, message: '请输入客服链接地址', trigger: 'blur' }]"> | ||||
|               <el-input size="small" placeholder="请输入客服链接地址" v-model="form.url"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="图标" prop="pictureUrl" style="width: 100%;" :rules="[{ required: true, message: '请上传图标 ', trigger: 'change' }]"> | ||||
|               <ai-uploader v-model="form.pictureUrl" :instance="instance" :limit="1"></ai-uploader> | ||||
|             </el-form-item> | ||||
|             <!-- <el-form-item label="权限配置" v-if="form.type === '0'" prop="pictureUrl" style="width: 100%;"> | ||||
|               <el-input disabled :value="girdName" size="small" placeholder="请选择地区"> | ||||
|                 <template slot="append"> | ||||
|                   <el-button size="small" @click="isShowArea = true">选择地区</el-button> | ||||
|                 </template> | ||||
|               </el-input> | ||||
|             </el-form-item> --> | ||||
|           </div> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|       <ai-dialog | ||||
|         title="选择权限" | ||||
|         :visible.sync="isShowArea" | ||||
|         :destroyOnClose="true" | ||||
|         @close="isShowArea = false" | ||||
|         @onConfirm="getCheckedTree" | ||||
|         width="720px"> | ||||
|         <el-tree | ||||
|           :data="treeList" | ||||
|           :props="defaultProps" | ||||
|           node-key="id" | ||||
|           check-strictly | ||||
|           ref="tree" | ||||
|           show-checkbox  | ||||
|           :default-checked-keys="defaultChecked" | ||||
|           :default-expanded-keys="defaultExpanded" | ||||
|           default-expand-all> | ||||
|         </el-tree> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import draggable from 'vuedraggable' | ||||
|   export default { | ||||
|     name: 'List', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       draggable | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         picked: [], | ||||
|         id: '', | ||||
|         isEdit: false, | ||||
|         isRemove: false, | ||||
|         defaultExpanded: [], | ||||
|         isRest: true, | ||||
|         isShowArea: false, | ||||
|         isLoading: false, | ||||
|         defaultProps: { | ||||
|           children: "children", | ||||
|           label: "label", | ||||
|         }, | ||||
|         treeList: [], | ||||
|         form: { | ||||
|           type: '', | ||||
|           pictureUrl: [], | ||||
|           url: '', | ||||
|           name: '', | ||||
|           checkType: '', | ||||
|           appId: '', | ||||
|           modulePath: '' | ||||
|         }, | ||||
|         typeDict: [{ | ||||
|           dictName: '外链小程序', | ||||
|           dictValue: '1' | ||||
|         }, { | ||||
|           dictName: '外链h5', | ||||
|           dictValue: '2' | ||||
|         }, { | ||||
|           dictName: '新闻', | ||||
|           dictValue: '3' | ||||
|         }, { | ||||
|           dictName: '客服', | ||||
|           dictValue: '4' | ||||
|         }], | ||||
|         info: {}, | ||||
|         isShowAdd: false, | ||||
|         list: [], | ||||
|         defaultChecked: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.dict.load('homeConfigMenuType', 'miniConfigCheckType').then(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.instance.post(`/app/appminihomeconfig/listAll`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.picked = res.data.picked | ||||
|             this.list = Object.keys(res.data.all).map(item => { | ||||
|               return { | ||||
|                 name: this.dict.getLabel('homeConfigMenuType', item), | ||||
|                 list: res.data.all[item] | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getCheckedTree () { | ||||
|         const keys = this.$refs.tree.getCheckedNodes(false, true).map(v => v.id) | ||||
|  | ||||
|         this.instance.post(`/app/appminihomeconfig/addOrUpdate`, { | ||||
|           ...this.info, | ||||
|           areaIds: keys | ||||
|         }).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.$message.success('修改成功') | ||||
|             this.isShowArea = false | ||||
|  | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       format (list) { | ||||
|         return list.map(item => { | ||||
|           if (item.girdLevel !== '2') { | ||||
|             item.disabled = true | ||||
|           } | ||||
|  | ||||
|           if (item.girdList && item.girdList.length) { | ||||
|             item.girdList = this.format(item.girdList) | ||||
|           } | ||||
|  | ||||
|           return item | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       editApp (e) { | ||||
|         if (e.type !== '0') { | ||||
|           this.form = { | ||||
|             ...e, | ||||
|             pictureUrl: [{ | ||||
|               url: e.pictureUrl | ||||
|             }] | ||||
|           } | ||||
|           this.isShowAdd = true | ||||
|  | ||||
|           return false | ||||
|         } | ||||
|          | ||||
|  | ||||
|         this.info = e | ||||
|         this.isLoading = true | ||||
|         this.instance.post(`/app/appminihomeconfig/queryDetailById?id=${e.id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             let parent = res.data.areaConfigs.map(v => { | ||||
|               v.label = v.name | ||||
|               v.children = [] | ||||
|  | ||||
|               return v | ||||
|             }).filter(e => !e.parentId)[0] | ||||
|             this.defaultExpanded = res.data.areaConfigs.filter(v => v.checked).map(v => v.id) | ||||
|             this.defaultChecked = res.data.areaConfigs.filter(v => v.checked).map(v => v.id) | ||||
|             this.addChild(parent, res.data.areaConfigs) | ||||
|             this.treeList = [parent] | ||||
|  | ||||
|             this.isShowArea = true | ||||
|           } | ||||
|  | ||||
|           this.isLoading = false | ||||
|         }).catch(() => { | ||||
|           this.isLoading = false | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       addChild(parent, list) { | ||||
|         for (let i = 0; i < list.length; i++) { | ||||
|           if (list[i].parentId === parent.id) { | ||||
|             parent.children.push(list[i]) | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (list.length > 0) { | ||||
|           parent['children'].map(v => this.addChild(v, list)) | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       isCanAdd (item) { | ||||
|         const isHas = this.picked.map(v => v.id).indexOf(item.id) > -1 | ||||
|  | ||||
|         return this.isEdit && item.picked !== '1' && !isHas | ||||
|       }, | ||||
|  | ||||
|       addApp (e) { | ||||
|         if (this.picked.length >= 8) { | ||||
|           return this.$message.error('导航功能最多放置8个') | ||||
|         } | ||||
|  | ||||
|         this.isRemove = false | ||||
|         this.picked.push(e) | ||||
|       }, | ||||
|  | ||||
|       eidt () { | ||||
|         if (this.isEdit) { | ||||
|           this.$confirm('确定退出编辑?').then(() => { | ||||
|             this.isEdit = false | ||||
|  | ||||
|             this.getList() | ||||
|           }) | ||||
|  | ||||
|           return false | ||||
|         } | ||||
|         this.isEdit = !this.isEdit | ||||
|       }, | ||||
|  | ||||
|       removeChoose (index) { | ||||
|         this.picked.splice(index, 1) | ||||
|  | ||||
|         this.isRest = false | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           this.isRest = true | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       save () { | ||||
|         this.instance.post(`/app/appminihomeconfig/updatePick?ids=${this.picked.map(v => v.id).join(',')}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.$message.success('保存成功') | ||||
|             this.isEdit = false | ||||
|             this.isRemove = false | ||||
|  | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onClose () { | ||||
|         this.form.type = '' | ||||
|         this.form.pictureUrl = [] | ||||
|         this.form.url = '' | ||||
|         this.form.name = '' | ||||
|         this.form.appId = '' | ||||
|         this.form.checkType = '' | ||||
|       }, | ||||
|  | ||||
|       onChange () { | ||||
|         this.form.url = '' | ||||
|         this.form.appId = '' | ||||
|       }, | ||||
|  | ||||
|       onConfirm () { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             this.instance.post(`/app/appminihomeconfig/addOrUpdate`, { | ||||
|               ...this.form, | ||||
|               pictureUrl: this.form.pictureUrl[0].url | ||||
|             }).then(res => { | ||||
|               if (res.code === 0) { | ||||
|                 this.$message.success('添加成功') | ||||
|                 this.isShowAdd = false | ||||
|  | ||||
|                 this.getList() | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       removeApp (id) { | ||||
|         this.$confirm('确定删除该数据?').then(() => { | ||||
|           this.instance.post(`/app/appminihomeconfig/delete?ids=${id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.isRemove = false | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       remove (id) { | ||||
|         this.$confirm('确定删除该数据?').then(() => { | ||||
|           this.instance.post(`/app/appapplicationinfo/delete?ids=${id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .list { | ||||
|     ::v-deep .ai-list__content { | ||||
|       padding: 0!important; | ||||
|  | ||||
|       .ai-list__content--right-wrapper { | ||||
|         background: transparent!important; | ||||
|         box-shadow: none!important; | ||||
|         margin: 0!important; | ||||
|         padding: 12px 0 12px!important; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .all { | ||||
|       .item-row { | ||||
|         display: flex; | ||||
|  | ||||
|         & > h2 { | ||||
|           margin-right: 40px; | ||||
|           font-weight: 500; | ||||
|           font-size: 16px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .item-wrapper { | ||||
|       display: flex; | ||||
|       flex-wrap: wrap; | ||||
|       flex: 1; | ||||
|       margin-bottom: 20px; | ||||
|  | ||||
|       .icon { | ||||
|         position: absolute; | ||||
|         top: 0; | ||||
|         right: 0; | ||||
|         z-index: 11; | ||||
|         font-size: 24px; | ||||
|         color: red; | ||||
|         transform: translate(50%, -20%); | ||||
|  | ||||
|         &:hover { | ||||
|           opacity: 0.6; | ||||
|           cursor: pointer; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .item { | ||||
|         position: relative; | ||||
|         margin: 0 16px 16px 0; | ||||
|         text-align: center; | ||||
|         cursor: pointer; | ||||
|  | ||||
|         .item-setting { | ||||
|           position: absolute; | ||||
|           top: 0; | ||||
|           left: 0; | ||||
|           z-index: 0; | ||||
|           opacity: 0; | ||||
|           width: 100%; | ||||
|           height: 100%; | ||||
|           transition: all ease 0.3s; | ||||
|  | ||||
|           .item-wrapper__icon { | ||||
|             position: relative; | ||||
|             z-index: 1; | ||||
|             width: 100%; | ||||
|             height: 100%; | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|             flex-direction: column; | ||||
|  | ||||
|             div { | ||||
|               margin-top: 6px; | ||||
|               font-size: 16px; | ||||
|             } | ||||
|           } | ||||
|  | ||||
|           i, div { | ||||
|             font-size: 16px; | ||||
|             color: #fff; | ||||
|           } | ||||
|  | ||||
|           .item-mask { | ||||
|             position: absolute; | ||||
|             top: 0; | ||||
|             left: 0; | ||||
|             width: 100%; | ||||
|             height: 100%; | ||||
|             background: rgba(0, 0, 0, 0.6); | ||||
|           } | ||||
|  | ||||
|           &:hover { | ||||
|             z-index: 1; | ||||
|             opacity: 1; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         img { | ||||
|           width: 60px; | ||||
|           height: 60px; | ||||
|           border-radius: 50%; | ||||
|         } | ||||
|  | ||||
|         h2 { | ||||
|           font-weight: normal; | ||||
|           font-size: 14px; | ||||
|           color: #666; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										40
									
								
								packages/extra/AppThematicConfig/AppThematicConfig.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								packages/extra/AppThematicConfig/AppThematicConfig.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <template> | ||||
|   <div class="AppThematicConfig"> | ||||
|     <List | ||||
|       slot="content" | ||||
|       :instance="instance" | ||||
|       :dict="dict" | ||||
|       :permissions="permissions"> | ||||
|     </List> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import List from './components/List.vue' | ||||
|  | ||||
|   export default { | ||||
|     name: 'AppThematicConfig', | ||||
|     label: '专题配置', | ||||
|  | ||||
|     components: { | ||||
|       List | ||||
|     }, | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .AppThematicConfig { | ||||
|     height: 100%; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										219
									
								
								packages/extra/AppThematicConfig/components/List.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								packages/extra/AppThematicConfig/components/List.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,219 @@ | ||||
| <template> | ||||
|   <ai-list> | ||||
|     <ai-title slot="title" title="专题配置" isShowBottomBorder></ai-title> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar bottomBorder> | ||||
|         <template #left> | ||||
|           <el-button type="primary" icon="iconfont iconAdd" size="small" @click="isShowAdd = true">添加 </el-button> | ||||
|         </template> | ||||
|         <template #right> | ||||
|           <el-input | ||||
|             v-model="search.name" | ||||
|             size="small" | ||||
|             placeholder="请输入专题名称" | ||||
|             clearable | ||||
|             v-throttle="() => {search.current = 1, getList()}" | ||||
|             @clear="search.current = 1, search.name = '', getList()" | ||||
|             suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table | ||||
|         :tableData="tableData" | ||||
|         :col-configs="colConfigs" | ||||
|         :total="total" | ||||
|         v-loading="loading" | ||||
|         style="margin-top: 16px;" | ||||
|         :current.sync="search.current" | ||||
|         :size.sync="search.size" | ||||
|         @getList="getList"> | ||||
|         <el-table-column slot="img" width="160px" label="首页封面" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <ai-uploader v-model="row.img" disabled :instance="instance" :limit="1"></ai-uploader> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column slot="options" width="160px" fixed="right" label="操作" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-options" style="padding-right: 30px;"> | ||||
|               <el-button type="text" @click="edit(row)">编辑</el-button> | ||||
|               <el-button type="text" @click="remove(row.id)">删除</el-button> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|       <ai-dialog | ||||
|         :visible.sync="isShowAdd" | ||||
|         width="680px" | ||||
|         height="580px" | ||||
|         :title="id ? '添加专题' : '编辑专题'" | ||||
|         @close="onClose" | ||||
|         @onConfirm="onConfirm"> | ||||
|         <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|           <div class="ai-form" :model="form" label-width="110px" label-position="right"> | ||||
|             <el-form-item label="专题名称" prop="name" style="width: 100%;" :rules="[{ required: true, message: '请输入专题名称', trigger: 'blur' }]"> | ||||
|               <el-input size="small" placeholder="请输入专题名称" v-model="form.name"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="首页封面" prop="pictureUrl" style="width: 100%;" :rules="[{ required: true, message: '请上传首页封面', trigger: 'change' }]"> | ||||
|               <ai-uploader v-model="form.pictureUrl" :instance="instance" :limit="1"></ai-uploader> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="应用类型" style="width: 100%;" prop="type" :rules="[{ required: true, message: '请选择应用类型', trigger: 'change' }]"> | ||||
|               <ai-select | ||||
|                 v-model="form.type" | ||||
|                 :selectList="typeDict" | ||||
|                 @change="onChange" | ||||
|                 laceholder="请选择应用类型"> | ||||
|               </ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="小程序appid" prop="appId" style="width: 100%;" v-if="form.type === '0'" :rules="[{ required: true, message: '请输入小程序appid', trigger: 'blur' }]"> | ||||
|               <el-input size="small" placeholder="请输入小程序appid" v-model="form.appId"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="链接" prop="url" style="width: 100%;" v-if="form.type === '1'" :rules="[{ required: true, message: '请输入链接', trigger: 'blur' }]"> | ||||
|               <el-input size="small" placeholder="请输入链接" v-model="form.url"></el-input> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'List', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         search: { | ||||
|           current: 1, | ||||
|           size: 10, | ||||
|           name: '' | ||||
|         }, | ||||
|         form: { | ||||
|           type: '1', | ||||
|           pictureUrl: [], | ||||
|           url: '', | ||||
|           name: '', | ||||
|           appId: '' | ||||
|         }, | ||||
|         typeDict: [{ | ||||
|           dictName: '外链小程序', | ||||
|           dictValue: '0' | ||||
|         }, { | ||||
|           dictName: '外链h5', | ||||
|           dictValue: '1' | ||||
|         }], | ||||
|         isShowAdd: false, | ||||
|         colConfigs: [ | ||||
|           { prop: 'name', label: '专题名称' }, | ||||
|           { slot: 'img', align: 'center' }, | ||||
|           { prop: 'type', align: 'center', label: '类型', formart: v => v === '0' ? '小程序' : '链接' }, | ||||
|           { prop: 'url', align: 'center', label: '链接' }, | ||||
|           { prop: 'appId', align: 'center', label: '小程序appid' }, | ||||
|           { prop: 'createTime', align: 'center', label: '创建时间' } | ||||
|         ], | ||||
|         id: '', | ||||
|         tableData: [], | ||||
|         total: 0, | ||||
|         loading: false | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.getList() | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.instance.post(`/app/appminitopicconfig/list`, null, { | ||||
|           params: { | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records.map(v => { | ||||
|               return { | ||||
|                 ...v, | ||||
|                 img: [{ | ||||
|                   url: v.pictureUrl | ||||
|                 }] | ||||
|               } | ||||
|             }) | ||||
|             this.total = res.data.total | ||||
|             this.loading = false | ||||
|           } else { | ||||
|             this.loading = false | ||||
|           } | ||||
|         }).catch(() => { | ||||
|           this.loading = false | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onChange () { | ||||
|         this.form.url = '' | ||||
|         this.form.appId = '' | ||||
|       }, | ||||
|  | ||||
|       onConfirm () { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             this.instance.post(`/app/appminitopicconfig/addOrUpdate`, { | ||||
|               ...this.form, | ||||
|               id: this.id || '', | ||||
|               pictureUrl: this.form.pictureUrl[0].url | ||||
|             }).then(res => { | ||||
|               if (res.code === 0) { | ||||
|                 this.$message.success('添加成功') | ||||
|                 this.isShowAdd = false | ||||
|  | ||||
|                 this.getList() | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       edit (e) { | ||||
|         this.id = e.id | ||||
|         this.form = { | ||||
|           ...e, | ||||
|           pictureUrl: [{ | ||||
|             url: e.pictureUrl | ||||
|           }] | ||||
|         } | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           this.isShowAdd = true | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onClose () { | ||||
|         this.id = '' | ||||
|         this.form.type = '1' | ||||
|         this.form.pictureUrl = [] | ||||
|         this.form.url = '' | ||||
|         this.form.name = '' | ||||
|         this.form.appId = '' | ||||
|       }, | ||||
|  | ||||
|       remove (id) { | ||||
|         this.$confirm('确定删除该数据?').then(() => { | ||||
|           this.instance.post(`/app/appminitopicconfig/delete?ids=${id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|  | ||||
| </style> | ||||
		Reference in New Issue
	
	Block a user