fix
This commit is contained in:
		
							
								
								
									
										210
									
								
								packages/wxwork/AppMassNotification/components/List.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								packages/wxwork/AppMassNotification/components/List.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| <template> | ||||
|   <ai-list class="List"> | ||||
|     <template #title> | ||||
|       <ai-title title="群发通知" isShowBottomBorder></ai-title> | ||||
|     </template> | ||||
|     <template #content> | ||||
|       <ai-search-bar> | ||||
|         <template #left> | ||||
|           <el-button type="primary" icon="iconfont iconAdd" @click="toAdd('')">添加</el-button> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table :tableData="tableData" :total="page.total" :current.sync="page.current" :size.sync="page.size" | ||||
|                 @getList="getTableData" show-overflow-tooltip :col-configs="colConfigs" :dict="dict"> | ||||
|         <!-- <el-table-column slot="type" width="240px" label="消息内容" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <el-popover | ||||
|               placement="bottom" | ||||
|               width="400" | ||||
|               :visible-arrow="false" | ||||
|               popper-class="wechat-message__container" | ||||
|               trigger="hover"> | ||||
|               <div class="count row-content" slot="reference" v-if="row.content">{{ row.content }}</div> | ||||
|               <div class="message-info"> | ||||
|                 <h2 :style="{marginBottom: row.accessUrl ? '16px' : '0'}">{{ row.content }}</h2> | ||||
|                 <div class="message-info__wrapper" v-if="row.accessUrl"> | ||||
|                   <img v-if="row.contentType == 'image'" :src="row.accessUrl"> | ||||
|                   <video style="width:40px; height: 40px;" v-if="row.contentType == 'video'" :src="row.accessUrl"></video> | ||||
|                   <img src="../../../../examples/assets/file.png" v-if="row.contentType == 'file'" width="40" height="40"/> | ||||
|                   <div class="message-info__wrapper--right"> | ||||
|                     <h3 v-if="row.contentType === 'image'">{{ row.media.file.name }}</h3> | ||||
|                     <h3 v-if="row.contentType === 'video'">{{ row.media.file.name }}</h3> | ||||
|                     <p v-if="row.contentType === 'image'">{{ row.media.file.fileSizeStr }}</p> | ||||
|                     <p v-if="row.contentType === 'video'">{{ row.media.file.fileSizeStr }}</p> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </el-popover> | ||||
|           </template> | ||||
|         </el-table-column>         --> | ||||
|         <el-table-column slot="options" label="操作" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <el-button type="text" @click="toAdd(row.id)">详情</el-button> | ||||
|             <!-- <el-button type="text" @click="handleDelete(row.id)">删除</el-button> --> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: "List", | ||||
|   props: { | ||||
|     dict: Object, | ||||
|     instance: Function, | ||||
|     params: Object, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       tableData: [], | ||||
|       page: {current: 1, size: 10, total: 0, pages: 0}, | ||||
|       id: '', | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTableData() | ||||
|   }, | ||||
|   computed: { | ||||
|     colConfigs() { | ||||
|       let conType = { | ||||
|         text: "文本", | ||||
|         image: "图片", | ||||
|         video: "视频", | ||||
|         file: "附件" | ||||
|       } | ||||
|       return [ | ||||
|         // { prop: "fileList", label: '消息类型', align: "center", width: "250px", formart: v => v?.map(e=> conType[e.contentType]).toString() }, | ||||
|         { prop: "fileList", label: '消息内容', align: "center", width: "250px", formart: v => v?.filter(e=> e.contentType == 'text')[0].content }, | ||||
|         // { prop: "fileList", label: '消息内容', align: "center", width: "250px", formart: v => v?.filter(e => e.contentType == 'text')[0].content}, | ||||
|         // { slot: 'type' }, | ||||
|         { prop: "messageSource", label: '消息类型', align: "center", formart: v => v==1? '居民': '居民群'}, | ||||
|         { prop: "createTime", label: '创建时间', align: "center", width: "250px"}, | ||||
|         { prop: "userName", label: '创建人', align: "center", width: "250px", }, | ||||
|         { slot: "options" ,}, | ||||
|       ] | ||||
|     }, | ||||
|     ...mapState(['user']) | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getTableData() { | ||||
|       this.instance.post(`/app/pushmessage/list?`, null, { | ||||
|         params: { | ||||
|           ...this.page, | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data.records | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     mapType(type) { | ||||
|       return { | ||||
|         'image': '图片', | ||||
|         'video': '视频', | ||||
|         'file': '文件', | ||||
|         'text': '文本' | ||||
|       }[type] | ||||
|     }, | ||||
|  | ||||
|     toAdd(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'Add', | ||||
|         params: { | ||||
|           id: id || '', | ||||
|         }, | ||||
|       }) | ||||
|     } | ||||
|  | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .List { | ||||
|   height: 100%; | ||||
|   background: #f3f4f5; | ||||
|  | ||||
|   .count { | ||||
|     cursor: pointer; | ||||
|     color: #2266FF; | ||||
|     font-size: 14px; | ||||
|  | ||||
|     &:hover { | ||||
|       opacity: 0.6; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| img, video { | ||||
|   width: 40px; | ||||
|   height: 40px; | ||||
|   margin-right: 10px; | ||||
|   object-fit: cover; | ||||
| } | ||||
|  | ||||
| .message-info { | ||||
|   padding: 8px; | ||||
|   min-height: 116px; | ||||
|  | ||||
|   h2 { | ||||
|     color: #222222; | ||||
|     font-weight: 500; | ||||
|     font-size: 14px; | ||||
|   } | ||||
|  | ||||
|   .message-info__wrapper { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     width: 368px; | ||||
|     height: 60px; | ||||
|     padding: 10px; | ||||
|     background: #FFFFFF; | ||||
|     border-radius: 2px; | ||||
|     border: 1px solid #D0D4DC; | ||||
|  | ||||
|     .message-info__wrapper--right { | ||||
|       flex: 1; | ||||
|       overflow: hidden; | ||||
|       text-overflow: ellipsis; | ||||
|       white-space: nowrap; | ||||
|     } | ||||
|  | ||||
|     h3 { | ||||
|       width: 100%; | ||||
|       color: #222222; | ||||
|       font-size: 14px; | ||||
|       overflow: hidden; | ||||
|       text-overflow: ellipsis; | ||||
|       white-space: nowrap; | ||||
|       font-weight: normal; | ||||
|     } | ||||
|  | ||||
|     img, video { | ||||
|       width: 40px; | ||||
|       height: 40px; | ||||
|       margin-right: 10px; | ||||
|       object-fit: cover; | ||||
|     } | ||||
|  | ||||
|     p { | ||||
|       margin-top: 6px; | ||||
|       font-size: 14px; | ||||
|       color: #888888; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .row-content { | ||||
|   white-space: nowrap; | ||||
|   overflow: hidden; | ||||
|   text-overflow: ellipsis; | ||||
| } | ||||
| </style> | ||||
| @@ -0,0 +1,195 @@ | ||||
| <template> | ||||
|   <section class="SelectDeptUser"> | ||||
|     <el-input :value="selectText" disabled size="small" @click.native="dialog=true"> | ||||
|       <el-button type="text" slot="append">开始选择</el-button> | ||||
|     </el-input> | ||||
|     <ai-dialog :visible.sync="dialog" title="选择部门/人员" width="700px" @onConfirm="handleSubmit" @close="selected=[],getDepts()"> | ||||
|       <el-breadcrumb separator="/"> | ||||
|         <el-breadcrumb-item v-for="(item, index) in selectDeptPath" :key="index"> | ||||
|           <el-button type="text" @click="deptNameClick(item)">{{ item.name }}</el-button> | ||||
|         </el-breadcrumb-item> | ||||
|       </el-breadcrumb> | ||||
|       <div class="optionsItem" v-for="(row, index) in options" :key="index"> | ||||
|         <el-row type="flex"> | ||||
|           <el-checkbox class="fill" :label="row.uid" v-model="row.checked" @change="handleCheck(row,index)">{{ row.name }}</el-checkbox> | ||||
|           <el-button type="text" v-if="!row.parentid&&row.kind=='dept'" @click="openDialogTag(row)">添加标签</el-button> | ||||
|           <el-button type="text" v-if="row.kind=='dept'" @click="itemClick(row)">更多</el-button> | ||||
|         </el-row> | ||||
|         <el-tag effect="dark" size="small" v-for="tag in row.selectedTags" :key="tag.id" class="mar-4">{{ tag.name }}</el-tag> | ||||
|       </div> | ||||
|       <ai-empty v-if="!options.length"/> | ||||
|       <ai-dialog :visible.sync="dialogTag" title="选择标签" width="500px" @onConfirm="handleSelectTag" @close="selectedTags=[]" append-to-body> | ||||
|         <el-checkbox-group v-model="selectedTags"> | ||||
|           <div class="optionsItem" v-for="(cls, index) in tagOps" :key="index"> | ||||
|             <ai-title :title="cls.name"/> | ||||
|             <el-checkbox class="fill" v-for="(op, i) in cls.tagList" :key="i" :label="op.id">{{ op.name }}</el-checkbox> | ||||
|           </div> | ||||
|         </el-checkbox-group> | ||||
|         <ai-empty v-if="!tagOps.length"/> | ||||
|       </ai-dialog> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "SelectDeptUser", | ||||
|   model: { | ||||
|     event: "change", | ||||
|     prop: "value" | ||||
|   }, | ||||
|   props: { | ||||
|     value: {default: ""}, | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     source: {default: 1} | ||||
|   }, | ||||
|   computed: { | ||||
|     selectText: v => v.value?.length > 0 ? "已选择" : "请选择", | ||||
|     tagAction: v => v.source == 2 ? '/app/wxcp/wxgroupchattag/listAllByCorp' : '/app/wxcp/wxcorptag/listAllByCorp' | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       dialog: false, | ||||
|       dialogTag: false, | ||||
|       currentCorp: {}, | ||||
|       selected: [], | ||||
|       selectDeptPath: [], | ||||
|       selectedTags: [], | ||||
|       options: [], | ||||
|       tagOps: [], | ||||
|       allData: [], | ||||
|       tags: {} | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getDepts() { | ||||
|       this.instance.post('/app/wxcp/wxdepartment/listAllByCorp').then(res => { | ||||
|         if (res?.data) { | ||||
|           let parents = res.data.map(e => e.parentid) | ||||
|           this.allData = res.data.map(e => ({ | ||||
|             ...e, | ||||
|             hasChildren: parents.includes(e.id), | ||||
|             uid: [e.corpId, e.id].join("_"), | ||||
|             kind: 'dept', | ||||
|             checked: false | ||||
|           })) | ||||
|           this.deptInit() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     getTagsByCorp(dvcpCorpId) { | ||||
|       return this.instance.post(this.tagAction, null, { | ||||
|         params: { | ||||
|           dvcpCorpId, | ||||
|           size: 9999 | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           return this.tagOps = res.data.records || [] | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     deptInit() { | ||||
|       this.options = this.allData.filter(e => !e.parentid) | ||||
|       this.selectDeptPath = [{name: "可选范围", id: ''}] | ||||
|     }, | ||||
|     itemClick(row) { | ||||
|       let index = this.selectDeptPath.findIndex(e => e.id == row.id) | ||||
|       if (index == -1) { | ||||
|         this.selectDeptPath.push(row) | ||||
|         this.getDeptsAndUsersByParent(row) | ||||
|       } | ||||
|     }, | ||||
|     getDeptsAndUsersByParent(row) { | ||||
|       let {id: departmentId, corpId: cid} = row | ||||
|       this.options = this.allData.filter(e => e.parentid == departmentId && e.corpId == cid) || [] | ||||
|       this.instance.post(`/app/wxcp/wxuser/listByDeptId`, null, { | ||||
|         params: {departmentId, status: 1, cid} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           res.data = res.data.map(e => ({ | ||||
|             ...e, kind: "user", checked: this.selected.some(s => { | ||||
|               if (e.id == s.id) return true | ||||
|             }) | ||||
|           })) | ||||
|           this.options = [this.options, res.data].flat() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     deptNameClick(row, index) { | ||||
|       if (!index) { //第一级别 | ||||
|         this.deptInit() | ||||
|       } else { | ||||
|         let length = this.selectDeptPath.length - index | ||||
|         this.selectDeptPath.splice(index + 1, length) | ||||
|         this.getDeptsAndUsersByParent(row.id) | ||||
|       } | ||||
|     }, | ||||
|     openDialogTag(row) { | ||||
|       this.getTagsByCorp(row.corpId).then(() => { | ||||
|         this.currentCorp = row | ||||
|         this.dialogTag = true | ||||
|       }) | ||||
|     }, | ||||
|     handleSelectTag() { | ||||
|       let {corpId} = this.currentCorp | ||||
|       this.currentCorp.selectedTags = this.$copy(this.tagOps.map(e => e.tagList).flat().filter(e => this.selectedTags.includes(e.id))) | ||||
|       this.tags[corpId] = this.$copy(this.currentCorp.selectedTags) | ||||
|       this.dialogTag = false | ||||
|     }, | ||||
|     handleSubmit() { | ||||
|       let result = {} | ||||
|       this.selected?.map(e => { | ||||
|         let {kind, id} = e | ||||
|         result[e.corpId] = [result[e.corpId], {kind, id}].flat() | ||||
|       }) | ||||
|       let selected = Object.keys(result).map(corpId => { | ||||
|         let res | ||||
|         if (result[corpId]) { | ||||
|           res = { | ||||
|             corpId, | ||||
|             objList: result[corpId].filter(e => !!e) | ||||
|           } | ||||
|           if (this.tags[corpId]?.length > 0) { | ||||
|             res.tagId = this.tags[corpId]?.map(e => e.id) | ||||
|           } | ||||
|         } | ||||
|         return res | ||||
|       }).filter(e => !!e) | ||||
|       this.$emit("change", selected) | ||||
|       this.dialog = false | ||||
|     }, | ||||
|     isSelected(uid) { | ||||
|       return !!this.selected.find(e => e.uid == uid) | ||||
|     }, | ||||
|     handleCheck(row, i) { | ||||
|       if (row.checked) { | ||||
|         this.selected.push(row) | ||||
|       } else { | ||||
|         this.selected.splice(i, 1) | ||||
|       } | ||||
|       this.$forceUpdate() | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getDepts() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .SelectDeptUser { | ||||
|   ::v-deep.optionsItem { | ||||
|     border: 1px solid #eee; | ||||
|     margin-bottom: 8px; | ||||
|     padding: 8px; | ||||
|     border-radius: 4px; | ||||
|  | ||||
|     .mar-4 { | ||||
|       margin-right: 4px; | ||||
|       margin-bottom: 4px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,157 +0,0 @@ | ||||
| <template> | ||||
|   <section class="AppDVDemo"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="数据大屏草稿板" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <div class="showPanel"> | ||||
|           <ai-dv-wrapper :views="views" v-model="active"> | ||||
|             <ai-echart :ops="ops" :data="views" theme="1"></ai-echart> | ||||
|           </ai-dv-wrapper> | ||||
|         </div> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|  | ||||
| import AiDvWrapper from "./layout/AiDvWrapper/AiDvWrapper"; | ||||
| import ops from './components/AiEchart/template/pie/pieChart3' | ||||
| import AiDvPanel from "./layout/AiDvPanel/AiDvPanel"; | ||||
| import AiDvDisplay from "./layout/AiDvDisplay/AiDvDisplay"; | ||||
| import AiDvSummary from "./layout/AiDvSummary/AiDvSummary"; | ||||
| import AiMonitor from "./components/AiMonitor/AiMonitor"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppDVDemo", | ||||
|   label: "数据大屏草稿板", | ||||
|   components: {AiMonitor, AiDvPanel, AiDvWrapper, AiDvDisplay, AiDvSummary}, | ||||
|   data() { | ||||
|     return { | ||||
|       ops, | ||||
|       active: '', | ||||
|       views: [ | ||||
|         { | ||||
|           "name": "阿斯达", | ||||
|           "v1": 23, | ||||
|           "v2": 33 | ||||
|         }, | ||||
|         { | ||||
|           "name": "水电费", | ||||
|           "v1": 12, | ||||
|           "v2": 34 | ||||
|         }, | ||||
|         { | ||||
|           "name": "凡哥", | ||||
|           "v1": 67, | ||||
|           "v2": 25 | ||||
|         }, | ||||
|         { | ||||
|           "name": "党费", | ||||
|           "v1": 98, | ||||
|           "v2": 85 | ||||
|         } | ||||
|       ], | ||||
|       list: [ | ||||
|         {name: '阿斯达', v1: 23, v2: 33}, | ||||
|         {name: '水电费', v1: 12, v2: 34}, | ||||
|         {name: '凡哥', v1: 67, v2: 25}, | ||||
|         {name: '党费', v1: 98, v2: 85}, | ||||
|         {name: '阿萨德', v1: 98, v2: 85}, | ||||
|         {name: '电饭锅', v1: 98, v2: 85}, | ||||
|         {name: '户籍科', v1: 98, v2: 85}, | ||||
|       ], | ||||
|       data: [ | ||||
|         { | ||||
|           "key": "阿斯达", | ||||
|           "value": '22', | ||||
|           "percentage": 33, | ||||
|           text: '同比上月' | ||||
|         }, | ||||
|         { | ||||
|           "key": "阿斯达", | ||||
|           "value": '22', | ||||
|           "percentage": -33, | ||||
|           text: '同比上月' | ||||
|         } | ||||
|       ], | ||||
|       value: [ | ||||
|         { | ||||
|           "key": "宅基地 ", | ||||
|           "value": 1252292, | ||||
|           "value1": 12592, | ||||
|           "value2": 12592, | ||||
|           "value3": 12592, | ||||
|           "value4": 12592 | ||||
|         }, | ||||
|         { | ||||
|           "key": "人数", | ||||
|           "value": 12592, | ||||
|           "value1": 12592, | ||||
|           "value2": 12592, | ||||
|           "value3": 12592, | ||||
|           "value4": 12592 | ||||
|         }, | ||||
|         { | ||||
|           "key": "户数 ", | ||||
|           "value": 12592, | ||||
|           "value1": 12592, | ||||
|           "value2": 12592, | ||||
|           "value3": 12592, | ||||
|           "value4": 12592 | ||||
|         }, | ||||
|         { | ||||
|           "key": "村社区", | ||||
|           "value": 12592, | ||||
|           "value1": 12592, | ||||
|           "value2": 12592, | ||||
|           "value3": 12592, | ||||
|           "value4": 12592 | ||||
|         } | ||||
|       ], | ||||
|       markers: [] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getMarkers() { | ||||
|       this.$request.post('/app/appcommunitybuildinginfo/listByBuildingAndHomestead', null, { | ||||
|         params: {current: 1, size: 1000000}, | ||||
|         withoutToken: true | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.markers = res.data.map(e => ({ | ||||
|             ...e, | ||||
|             icon: "https://cdn.cunwuyun.cn/dvcp/dv/monitor.svg", | ||||
|             label: e.communityName | ||||
|           })) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     // this.getMarkers() | ||||
|     setTimeout(() => { | ||||
|       this.list = this.list.map(e => ({name: e.name, '电费': e.v1, '水费': e.v2 * 2})) | ||||
|     }, 2000) | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.$initWxOpenData() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| @import "./lib/animation"; | ||||
|  | ||||
| .AppDVDemo { | ||||
|   height: 100%; | ||||
|  | ||||
|   .showPanel { | ||||
|     height: 600px; | ||||
|   } | ||||
|  | ||||
|   .AiDvPanel { | ||||
|     width: 600px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										88
									
								
								project/dvui/components/AiDataPanel.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								project/dvui/components/AiDataPanel.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| <template> | ||||
|   <section class="AiDataPanel"> | ||||
|     <b class="item-title" v-text="label"/> | ||||
|     <div class="num-bg"> | ||||
|       <span ref="num" class="num" v-text="num"/> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {gsap} from 'gsap' | ||||
|  | ||||
| export default { | ||||
|   name: "AiDataPanel", | ||||
|   props: { | ||||
|     label: {default: "标题"}, | ||||
|     value: {default: 0} | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       num: 0 | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     animation() { | ||||
|       let demo = {num: Math.max(this.value - 30, 0)} | ||||
|       gsap.to(demo, 1, { | ||||
|         num: this.value, onUpdate: () => { | ||||
|           this.num = demo.num?.toFixed(0) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.animation() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AiDataPanel { | ||||
|   flex: 1; | ||||
|   width: 172px; | ||||
|   height: 160px; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   align-items: center; | ||||
|   background: #000; | ||||
|  | ||||
|   & + .AiDataPanel { | ||||
|     margin-left: 16px; | ||||
|   } | ||||
|  | ||||
|   .item-title { | ||||
|     font-size: 24px; | ||||
|     line-height: 32px; | ||||
|     background-image: -webkit-linear-gradient(bottom, #35BEFF, #EBF9FF, #FFFFFF); | ||||
|     -webkit-background-clip: text; | ||||
|     -webkit-text-fill-color: transparent; | ||||
|     margin-top: 30px; | ||||
|   } | ||||
|  | ||||
|   .num-bg { | ||||
|     width: 100%; | ||||
|     height: 160px; | ||||
|     background-image: url(https://cdn.cunwuyun.cn/dvcp/dv/dianjiang/number-bg.png); | ||||
|     background-size: 100% 100%; | ||||
|     position: relative; | ||||
|     margin-top: -76px; | ||||
|  | ||||
|     .num { | ||||
|       position: absolute; | ||||
|       left: 0; | ||||
|       bottom: 30px; | ||||
|       width: 100%; | ||||
|       text-align: center; | ||||
|       height: 50px; | ||||
|       font-size: 40px; | ||||
|       font-family: D-DIN-Bold, D-DIN; | ||||
|       font-weight: bold; | ||||
|       line-height: 54px; | ||||
|       background-image: -webkit-linear-gradient(bottom, #35BEFF, #EBF9FF, #FFFFFF); | ||||
|       -webkit-background-clip: text; | ||||
|       -webkit-text-fill-color: transparent; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										357
									
								
								project/dvui/components/AiDvRender.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										357
									
								
								project/dvui/components/AiDvRender.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,357 @@ | ||||
| <template> | ||||
|   <div class="AiDvRender" style="width: 100%; height: 100%;"> | ||||
|     <ai-dv-display v-if="data.type === 'display'" :title="data.title" :list="values"></ai-dv-display> | ||||
|     <ai-dv-panel | ||||
|         style="height: 100%; width: 100%;" | ||||
|         v-if="data.type !== 'display'" | ||||
|         :title="data.title" | ||||
|         :border="data.border || ''"> | ||||
|       <AiDvSummary v-if="data.type === 'summary'" :summaryTitle="data.summaryTitle" :key="`summary${index}`" :type="data.display" :data="values"/> | ||||
|       <AiSwiper v-else-if="data.type === 'swiper'" :heigth="'100%'" :data="values"/> | ||||
|       <dv-scroll-board | ||||
|           v-if="data.type === 'table'" | ||||
|           :class="'dvScrollBoard' + theme" | ||||
|           :config="formatTable(values, data.isShowIndex, data.rowNum)" | ||||
|           :key="data.height" | ||||
|           :theme="theme" | ||||
|           :style="{height: data.height + 'px', width: '100%'}"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'barChart1'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="data.config"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'barChart2'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :theme="theme" | ||||
|           :key="`chart${index}`" | ||||
|           :data="values" | ||||
|           :ops="data.config"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'barChart3'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="data.config"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'barChart5'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="data.config"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'barChart7'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="data.config"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'barChart8'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="data.config"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'barChart9'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="data.config"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'lineChart1'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="lineChart1"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'lineChart2'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="lineChart2"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'lineChart3'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="data.config"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'lineChart4'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="data.config"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'lineChart5'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="lineChart5"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'pieChart'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="pieChart"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'pieChart1'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="pieChart1"/> | ||||
|       <ai-echart | ||||
|           v-else-if="data.type === 'pieChart3'" | ||||
|           style="height: 100%; width: 100%;" | ||||
|           :ref="'chart' + index" | ||||
|           :key="`chart${index}`" | ||||
|           :theme="theme" | ||||
|           :data="values" | ||||
|           :ops="pieChart3"/> | ||||
|       <ai-map :markers="values" v-else-if="data.type=='map'" :mask="data.mask === '1'" :areaId="data.areaId || user.info.areaId" | ||||
|               :map-style="`amap://styles/${data.mapStyle}`" :pulseLines="data.pulseLines==1" :map.sync="map" :lib.sync="lib"/> | ||||
|       <ai-monitor :src="data.src" v-else-if="data.type === 'monitor'" :type="data.monitorType"/> | ||||
|       <video style="width: 100%; height: 100%; object-fit: fill;" loop :src="data.src" autoplay v-else-if="data.type === 'video'"/> | ||||
|       <AiDvPartyOrg style="width: 100%; height: 100%;" v-else-if="data.type === 'partyOrg'" :instance="instance"/> | ||||
|     </ai-dv-panel> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
| import AiSwiper from './AiSwiper.vue' | ||||
| import pieChart from './AiEchart/template/pie/pieChart2' | ||||
| import pieChart1 from './AiEchart/template/pie/pieChart1' | ||||
| import pieChart3 from './AiEchart/template/pie/pieChart3' | ||||
| import lineChart1 from './AiEchart/template/line/lineChart1' | ||||
| import lineChart2 from './AiEchart/template/line/lineChart2' | ||||
| import lineChart5 from './AiEchart/template/line/lineChart5' | ||||
| import AiMonitor from "./AiMonitor/AiMonitor"; | ||||
| import AiDvPanel from "../layout/AiDvPanel/AiDvPanel"; | ||||
| import AiDvDisplay from "../layout/AiDvDisplay/AiDvDisplay"; | ||||
| import AiDvSummary from "../layout/AiDvSummary/AiDvSummary"; | ||||
|  | ||||
|  | ||||
| export default { | ||||
|   name: 'AiDvRender', | ||||
|   props: ['data', 'index', 'theme', 'instance'], | ||||
|   components: { | ||||
|     AiDvSummary, | ||||
|     AiDvDisplay, | ||||
|     AiDvPanel, | ||||
|     AiMonitor, | ||||
|     AiSwiper | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       lineChart1, | ||||
|       lineChart2, | ||||
|       lineChart5, | ||||
|       pieChart, | ||||
|       pieChart1, | ||||
|       pieChart3, | ||||
|       map: null, | ||||
|       lib: null | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     values() { | ||||
|       if (!this.data) { | ||||
|         return [] | ||||
|       } | ||||
|  | ||||
|       return this.data.type === 'map' ? this.data[this.data.dataType].map(e => { | ||||
|         return {...e, lng: e['经度'], lat: e['纬度'], label: e['地区名称']} | ||||
|       }) : this.data[this.data.dataType] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     formatTable(data, isShowIndex, rowNum) { | ||||
|       if (!data.length) { | ||||
|         return { | ||||
|           header: [], | ||||
|           data: [] | ||||
|         } | ||||
|       } | ||||
|       let rows = [] | ||||
|       const header = data.map(v => { | ||||
|         return v[Object.keys(v)[0]] | ||||
|       }) | ||||
|       Object.keys(data[0]).forEach((item, index) => { | ||||
|         if (index !== 0) { | ||||
|           rows.push(item) | ||||
|         } | ||||
|       }) | ||||
|       return { | ||||
|         header: header, | ||||
|         data: rows.map(item => { | ||||
|           return data.map(v => { | ||||
|             return v[item] | ||||
|           }) | ||||
|         }), | ||||
|         headerBGC: 'transparent', | ||||
|         evenRowBGC: 'transparent', | ||||
|         oddRowBGC: 'rgba(0, 133, 255, 0.2)', | ||||
|         headerHeight: 42, | ||||
|         rowNum: rowNum || 7, | ||||
|         index: isShowIndex === '1', | ||||
|         waitTime: 8000, | ||||
|         carousel: 'page', | ||||
|         indexHeader: '排名', | ||||
|         align: ['center', 'center', 'center', 'center', 'center'] | ||||
|       } | ||||
|     }, | ||||
|     handleMapClick(count = 0) { | ||||
|       let {lib: AMap, map} = this | ||||
|       if (AMap) { | ||||
|         let infoWin = new AMap.InfoWindow({content: ""}) | ||||
|         map.clearMap() | ||||
|         let markers = this.values.filter(e => e.lng).map(e => { | ||||
|           return new AMap.Marker({ | ||||
|             map, | ||||
|             label: e.label, | ||||
|             icon: e.icon, | ||||
|             position: [e.lng, e.lat] | ||||
|           }).on('click', ({target}) => { | ||||
|             map.clearInfoWindow() | ||||
|             markers?.map(m => m.getIcon() == e.selectedIcon && m.setIcon(e.icon)) | ||||
|             target.setIcon(e.selectedIcon) | ||||
|             infoWin.setContent([ | ||||
|               `<div class="infoWin">`, | ||||
|               `<b>${e.label}</b>`, | ||||
|               `<div>累计成交金额:${e['累计成交金额(万)']}万元</div>`, | ||||
|               `<div>金融产品:${e['金融产品(万)']}万元</div>`, | ||||
|               `<div>融资需求:${e['融资需求(万)']}万元</div>`, | ||||
|               '</div>' | ||||
|             ].join('')) | ||||
|             infoWin.open(map, [e.lng, e.lat]) | ||||
|           }) | ||||
|         }) | ||||
|         map.setFitView(markers) | ||||
|       } else if (count < 10) { | ||||
|         console.log("正在加载...%s", count) | ||||
|         setTimeout(() => this.handleMapClick(++count), 1000) | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     if (this.data.type == 'map') { | ||||
|       this.handleMapClick() | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AiDvRender { | ||||
|   ::v-deep .dvScrollBoard1 { | ||||
|  | ||||
|     .header { | ||||
|       background: rgba(0, 0, 0, 0.1) !important; | ||||
|  | ||||
|       .header-item { | ||||
|         color: #FFBB73 !important; | ||||
|         font-size: 16px !important; | ||||
|         font-weight: 600; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     .rows { | ||||
|       font-size: 16px; | ||||
|       font-weight: 600; | ||||
|       color: #FFFFFF; | ||||
|       line-height: 21px; | ||||
|       text-shadow: 0px 2px 4px rgba(117, 9, 9, 0.5); | ||||
|       background: linear-gradient(180deg, #FFF6C7 0%, #FF9A02 100%); | ||||
|       -webkit-background-clip: text; | ||||
|       -webkit-text-fill-color: transparent; | ||||
|  | ||||
|       & > div:nth-of-type(2n - 1) { | ||||
|         background-color: transparent !important; | ||||
|       } | ||||
|  | ||||
|       & > div:nth-of-type(2n) { | ||||
|         background-color: rgba(0, 0, 0, 0.1) !important; | ||||
|       } | ||||
|  | ||||
|       .index { | ||||
|         color: #fff; | ||||
|         text-shadow: none; | ||||
|         background: #BD4921 !important; | ||||
|         -webkit-background-clip: inherit; | ||||
|         -webkit-text-fill-color: #fff; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep.amap-info-contentContainer { | ||||
|     .amap-info-content { | ||||
|       background: #0A3257; | ||||
|       border: 1px solid #7BE5FF; | ||||
|       padding: 16px; | ||||
|       font-family: PingFangSC-Semibold, PingFang SC; | ||||
|  | ||||
|       .infoWin { | ||||
|         & > b { | ||||
|           display: block; | ||||
|           font-size: 18px; | ||||
|           font-weight: 600; | ||||
|           color: #FFFFFF; | ||||
|           margin-bottom: 13px; | ||||
|         } | ||||
|  | ||||
|         & > div { | ||||
|           font-size: 16px; | ||||
|           font-weight: 400; | ||||
|           color: #7BE5FF; | ||||
|  | ||||
|           & + div { | ||||
|             margin-top: 8px; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .amap-info-sharp { | ||||
|       border-top-color: #0A3257; | ||||
|  | ||||
|       &:after { | ||||
|         border-top-color: #7BE5FF; | ||||
|         filter: none; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										30
									
								
								project/dvui/components/AiStaData.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								project/dvui/components/AiStaData.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| <template> | ||||
|   <section class="AiStaData"> | ||||
|     <ai-data-panel v-for="op in data" :key="op[key]" | ||||
|                    :label="op[label]" :value="op[key]"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AiDataPanel from "./AiDataPanel"; | ||||
|  | ||||
| export default { | ||||
|   name: "AiStaData", | ||||
|   components: {AiDataPanel}, | ||||
|   props: { | ||||
|     data: {default: () => []}, | ||||
|     key: {default: "id"}, | ||||
|     label: {default: "label"}, | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AiStaData { | ||||
|   width: 100%; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   flex-wrap: wrap; | ||||
|   justify-content: center; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										92
									
								
								project/dvui/components/AiSwiper.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								project/dvui/components/AiSwiper.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| <template> | ||||
|   <div class="swiper"> | ||||
|     <el-carousel height="100%" indicator-position="none"> | ||||
|       <el-carousel-item v-for="(item, index) in data" :key="index"> | ||||
|         <img :src="item.img"> | ||||
|         <div class="swiper-content" v-if="item.title"> | ||||
|           <h2>{{ item.title }}</h2> | ||||
|           <p>{{ item.content }}</p> | ||||
|         </div> | ||||
|       </el-carousel-item> | ||||
|     </el-carousel> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'AiSwiper', | ||||
|  | ||||
|     props: { | ||||
|       data: { | ||||
|         type: Array, | ||||
|         default: () => [] | ||||
|       }, | ||||
|  | ||||
|       width: { | ||||
|         type: String, | ||||
|         default: '100%' | ||||
|       }, | ||||
|       heigth: { | ||||
|         type: String, | ||||
|         default: '100%' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|  | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|  | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|  | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .swiper { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     padding: 20px 0 0; | ||||
|  | ||||
|     ::v-deep .el-carousel { | ||||
|       height: 100%; | ||||
|     } | ||||
|  | ||||
|     img { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|     } | ||||
|  | ||||
|     .swiper-content { | ||||
|       position: absolute; | ||||
|       bottom: 0; | ||||
|       left: 0; | ||||
|       z-index: 1; | ||||
|       width: 100%; | ||||
|       padding: 10px; | ||||
|       text-align: center; | ||||
|       background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, #000000 100%); | ||||
|  | ||||
|       h2 { | ||||
|         margin-bottom: 4px; | ||||
|         color: #fff; | ||||
|         text-align: center; | ||||
|         font-size: 18px; | ||||
|       } | ||||
|  | ||||
|       p { | ||||
|         line-height: 22px; | ||||
|         white-space: pre-line; | ||||
|         color: #B6DFFF; | ||||
|         font-size: 14px; | ||||
|         text-align: center; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										62
									
								
								project/oms/apps/develop/AppAiCode/AppAiCode.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								project/oms/apps/develop/AppAiCode/AppAiCode.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| <template> | ||||
|   <section class="AppAiCode"> | ||||
|     <component :is="currentPage" v-bind="$props"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AcList from "./acList"; | ||||
| import AcAdd from "./acAdd"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppAiCode", | ||||
|   components: {AcAdd, AcList}, | ||||
|   label: "低代码生成平台", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     currentPage() { | ||||
|       let {hash} = this.$route | ||||
|       return hash == "#add" ? AcAdd : AcList | ||||
|     } | ||||
|   }, | ||||
|   provide() { | ||||
|     return { | ||||
|       top: this | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     handleGetCode(id) { | ||||
|       id && this.instance.post("/node/aicode/getCode", null, { | ||||
|         params: {id}, | ||||
|         responseType: "blob" | ||||
|       }).then(res => { | ||||
|         if (res?.code == 1) { | ||||
|           this.$message.error(res.err) | ||||
|         } else { | ||||
|           const link = document.createElement('a') | ||||
|           let blob = new Blob([res], {type: 'application/zip'}) | ||||
|           link.style.display = 'none' | ||||
|           link.href = URL.createObjectURL(blob) | ||||
|           link.setAttribute('download', 'aicode.zip') | ||||
|           document.body.appendChild(link) | ||||
|           link.click() | ||||
|           document.body.removeChild(link) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load("detailType") | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppAiCode { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										185
									
								
								project/oms/apps/develop/AppAiCode/acAdd.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								project/oms/apps/develop/AppAiCode/acAdd.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,185 @@ | ||||
| <template> | ||||
|   <section class="acAdd"> | ||||
|     <ai-detail list> | ||||
|       <ai-title slot="title" :title="pageTitle"> | ||||
|         <template #rightBtn> | ||||
|           <el-button type="primary" v-if="isEdit" @click="top.handleGetCode($route.query.id)">生成代码</el-button> | ||||
|         </template> | ||||
|       </ai-title> | ||||
|       <template #content> | ||||
|         <el-form ref="AcForm" :model="form" size="small" label-width="120px" :rules="rules"> | ||||
|           <el-tabs tab-position="left" @tab-click="handleSyncProps"> | ||||
|             <el-tab-pane label="基本信息" lazy> | ||||
|               <ai-card title="基本信息"> | ||||
|                 <template #content> | ||||
|                   <el-row type="flex"> | ||||
|                     <div class="fill"> | ||||
|                       <el-form-item label="应用名称" prop="name"> | ||||
|                         <el-input v-model="form.name" clearable placeholder="请输入"/> | ||||
|                       </el-form-item> | ||||
|                       <el-form-item label="应用模块" prop="appName"> | ||||
|                         <el-input v-model="form.appName" clearable placeholder="请输入"/> | ||||
|                       </el-form-item> | ||||
|                     </div> | ||||
|                     <div class="fill"> | ||||
|                       <el-form-item label="核心码" prop="rightCode"> | ||||
|                         <el-input v-model="form.rightCode" clearable placeholder="请输入"/> | ||||
|                       </el-form-item> | ||||
|                       <el-form-item label="详情方式" prop="detailType"> | ||||
|                         <ai-select v-model="form.detailType" :selectList="dict.getDict('detailType')"/> | ||||
|                       </el-form-item> | ||||
|                     </div> | ||||
|                   </el-row> | ||||
|                   <el-form-item label="按钮配置" prop="btns"> | ||||
|                     <el-checkbox-group v-model="form.btns"> | ||||
|                       <el-checkbox label="insertEnable">添加</el-checkbox> | ||||
|                       <el-checkbox label="importEnable">导入</el-checkbox> | ||||
|                       <el-checkbox label="exportEnalbe">导出</el-checkbox> | ||||
|                       <el-checkbox label="editEnable">编辑</el-checkbox> | ||||
|                       <el-checkbox label="deleteEnable">删除</el-checkbox> | ||||
|                       <el-checkbox label="batchDelEnable">批量删除</el-checkbox> | ||||
|                     </el-checkbox-group> | ||||
|                   </el-form-item> | ||||
|                 </template> | ||||
|               </ai-card> | ||||
|               <ai-card title="字段设置"> | ||||
|                 <template #right> | ||||
|                   <el-button type="text" @click="handleAddProps">批量添加</el-button> | ||||
|                   <el-button type="text" @click="form.props.push({})">添加</el-button> | ||||
|                 </template> | ||||
|                 <template #content> | ||||
|                   <ai-table :tableData="form.props" :isShowPagination="false" :colConfigs="colConfigs"> | ||||
|                     <el-table-column v-for="col in colConfigs" :key="col.slot" v-bind="col"> | ||||
|                       <template slot-scope="{row}"> | ||||
|                         <el-checkbox v-if="col.type=='checkBox'" v-model="row[col.slot]"/> | ||||
|                         <span v-else-if="col.type=='chbShow'" v-text="row[col.slot]==true?'✔':''"/> | ||||
|                         <el-input v-else size="small" v-model="row[col.slot]" placeholder="请输入" clearable/> | ||||
|                       </template> | ||||
|                     </el-table-column> | ||||
|                     <el-table-column label="操作" slot="options" align="center"> | ||||
|                       <template slot-scope="{row,$index}"> | ||||
|                         <el-button type="text" @click="form.props.splice($index,1)">删除</el-button> | ||||
|                       </template> | ||||
|                     </el-table-column> | ||||
|                   </ai-table> | ||||
|                 </template> | ||||
|               </ai-card> | ||||
|             </el-tab-pane> | ||||
|             <el-tab-pane label="详情设计" lazy> | ||||
|               <detail-layout v-bind="$props" :form="form" v-model="form.detailConfig"/> | ||||
|             </el-tab-pane> | ||||
|           </el-tabs> | ||||
|         </el-form> | ||||
|       </template> | ||||
|       <template #footer> | ||||
|         <el-button @click="back">取消</el-button> | ||||
|         <el-button type="primary" @click="submit">提交</el-button> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import DetailLayout from "./detailLayout"; | ||||
|  | ||||
| export default { | ||||
|   name: "acAdd", | ||||
|   components: {DetailLayout}, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   inject: { | ||||
|     top: {} | ||||
|   }, | ||||
|   computed: { | ||||
|     isEdit: v => !!v.$route.query.id, | ||||
|     pageTitle: v => v.isEdit ? "编辑应用" : "新增应用" | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       form: {props: [], btns: []}, | ||||
|       rules: { | ||||
|         name: {required: true, message: "请输入应用名称"}, | ||||
|         appName: {required: true, message: "请输入应用模块"}, | ||||
|         btns: {required: true, message: '请输入按钮配置', trigger: 'change'} | ||||
|       }, | ||||
|       colConfigs: [ | ||||
|         {slot: 'prop', label: "字段"}, | ||||
|         {slot: 'label', label: "名称"}, | ||||
|         {slot: 'dict', label: "字典"}, | ||||
|         {slot: 'isSearch', label: "搜索字段", align: 'center', type: 'checkBox'}, | ||||
|         {slot: 'isTable', label: "表格字段", align: 'center', type: 'checkBox'}, | ||||
|         {slot: 'isDetail', label: "详情字段", align: 'center', type: 'chbShow'}, | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getDetail() { | ||||
|       let {id} = this.$route.query | ||||
|       id && this.instance.post("/node/aicode/detail", null, { | ||||
|         params: {id} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.form = res.data | ||||
|           this.handleSyncProps() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     back() { | ||||
|       this.$router.push({}) | ||||
|     }, | ||||
|     submit() { | ||||
|       this.$refs.AcForm.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post("/node/aicode/addOrUpdate", this.form).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success("提交成功!") | ||||
|               this.back() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleSyncProps() { | ||||
|       let detailPorps = this.form.detailConfig?.map(e => e.column)?.flat()?.map(e => e.prop) | ||||
|       this.form.props = this.form.props.map(e => ({...e, isDetail: !!detailPorps?.includes(e.prop)})) | ||||
|     }, | ||||
|     handleAddProps() { | ||||
|       this.$prompt("请输入swagger示例JSON字符串", { | ||||
|         type: 'warning', | ||||
|         title: "批量添加字段", | ||||
|         dangerouslyUseHTMLString: true, | ||||
|         center: true, | ||||
|       }).then(({value}) => { | ||||
|         if (this.$checkJson(value)) { | ||||
|           Object.keys(JSON.parse(value)).map(prop => { | ||||
|             this.form.props.push({prop}) | ||||
|           }) | ||||
|         } | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     $checkJson(str) { | ||||
|       if (typeof str == 'string') { | ||||
|         try { | ||||
|           let obj = JSON.parse(str); | ||||
|           return !!(typeof obj == 'object' && obj); | ||||
|         } catch (e) { | ||||
|           return false; | ||||
|         } | ||||
|       } | ||||
|       return false; | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     this.getDetail() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .acAdd { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										90
									
								
								project/oms/apps/develop/AppAiCode/acList.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								project/oms/apps/develop/AppAiCode/acList.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| <template> | ||||
|   <section class="acList"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="低代码生成平台" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <el-button type="primary" icon="iconfont iconAdd" @click="handleAdd()">添加</el-button> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input size="small" placeholder="搜索应用" v-model="search.name" clearable | ||||
|                       @change="page.current=1,getTableData()"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :total="page.total" :current.sync="page.current" :size.sync="page.size" | ||||
|                   @getList="getTableData" :col-configs="colConfigs" :dict="dict"> | ||||
|           <el-table-column slot="options" label="操作" fixed="right" align="center" width="300"> | ||||
|             <template slot-scope="{row}"> | ||||
|               <el-button type="text" @click="handleAdd(row.id)">编辑</el-button> | ||||
|               <el-button type="text" @click="handleDelete(row.id)">删除</el-button> | ||||
|               <el-button type="text" @click="top.handleGetCode(row.id)">下载</el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "acList", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   inject: { | ||||
|     top: {} | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       search: {name: ""}, | ||||
|       page: {current: 1, size: 10, total: 0}, | ||||
|       tableData: [], | ||||
|       colConfigs: [ | ||||
|         {label: "应用名称", prop: "name", width: 200}, | ||||
|         {label: "应用模块", prop: "appName"}, | ||||
|         {label: "权限码", prop: "rightCode"}, | ||||
|         {label: "详情展示方式", prop: "detailType", dict: "detailType"}, | ||||
|       ], | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getTableData() { | ||||
|       this.instance.post("/node/aicode/list", null, { | ||||
|         params: {...this.page, ...this.search} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data.records | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleAdd(id) { | ||||
|       this.$router.push({hash: "#add", query: {id}}) | ||||
|     }, | ||||
|     handleDelete(ids) { | ||||
|       this.$confirm("是否要删除该应用?").then(() => { | ||||
|         this.instance.post("/node/aicode/delete", null, { | ||||
|           params: {ids} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("删除成功") | ||||
|             this.getTableData() | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTableData() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .acList { | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										274
									
								
								project/oms/apps/develop/AppAiCode/config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								project/oms/apps/develop/AppAiCode/config.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,274 @@ | ||||
| { | ||||
|   "config": [ | ||||
|     { | ||||
|       "type": "info", | ||||
|       "tips": "(不能重复添加同一元素)", | ||||
|       "label": "信息", | ||||
|       "children": [ | ||||
|         { | ||||
|           "type": "name", | ||||
|           "fieldName": "姓名", | ||||
|           "fieldTips": "请输入姓名", | ||||
|           "fixedLabel": "姓名", | ||||
|           "disable": "0", | ||||
|           "grid": 0.5, | ||||
|           "defaultValue": "", | ||||
|           "icon": "icontext_box", | ||||
|           "mustFill": "1", | ||||
|           "maxLength": 20 | ||||
|         }, | ||||
|         { | ||||
|           "type": "idNumber", | ||||
|           "fieldName": "身份证号", | ||||
|           "fixedLabel": "身份证号", | ||||
|           "fieldTips": "请输入身份证号", | ||||
|           "defaultValue": "", | ||||
|           "icon": "icontext_area", | ||||
|           "mustFill": "1", | ||||
|           "maxLength": 20, | ||||
|           "disable": "0", | ||||
|           "grid": 0.5 | ||||
|         }, | ||||
|         { | ||||
|           "type": "phone", | ||||
|           "fieldName": "联系方式", | ||||
|           "fixedLabel": "联系方式", | ||||
|           "fieldTips": "请输入联系方式", | ||||
|           "defaultValue": "", | ||||
|           "icon": "icontext_area", | ||||
|           "mustFill": "1", | ||||
|           "maxLength": 20, | ||||
|           "disable": "0", | ||||
|           "grid": 0.5 | ||||
|         }, | ||||
|         { | ||||
|           "type": "area", | ||||
|           "fieldName": "地区", | ||||
|           "fixedLabel": "地区", | ||||
|           "fieldTips": "请选择地区", | ||||
|           "defaultValue": "", | ||||
|           "icon": "icontext_area", | ||||
|           "mustFill": "1", | ||||
|           "areaPattern": "", | ||||
|           "disable": "0", | ||||
|           "grid": 0.5 | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "type": "options", | ||||
|       "tips": "(可重复添加)", | ||||
|       "label": "选项", | ||||
|       "children": [ | ||||
|         { | ||||
|           "type": "radio", | ||||
|           "fieldName": "单选", | ||||
|           "fixedLabel": "单选", | ||||
|           "fieldTips": "请选择", | ||||
|           "grid": 0.5, | ||||
|           "icon": "iconradio", | ||||
|           "mustFill": "1", | ||||
|           "disable": "0", | ||||
|           "defaultValue": "", | ||||
|           "options": [ | ||||
|             { | ||||
|               "label": "选项1", | ||||
|               "value": "" | ||||
|             }, | ||||
|             { | ||||
|               "label": "选项2", | ||||
|               "value": "" | ||||
|             } | ||||
|           ], | ||||
|           "title": "" | ||||
|         }, | ||||
|         { | ||||
|           "type": "checkbox", | ||||
|           "fieldName": "多选", | ||||
|           "fixedLabel": "多选", | ||||
|           "fieldTips": "请选择", | ||||
|           "icon": "iconcheck_box", | ||||
|           "mustFill": "1", | ||||
|           "grid": 0.5, | ||||
|           "disable": "0", | ||||
|           "defaultValue": [], | ||||
|           "options": [ | ||||
|             { | ||||
|               "label": "选项1", | ||||
|               "value": "" | ||||
|             }, | ||||
|             { | ||||
|               "label": "选项2", | ||||
|               "value": "" | ||||
|             } | ||||
|           ], | ||||
|           "title": "" | ||||
|         }, | ||||
|         { | ||||
|           "type": "select", | ||||
|           "fieldName": "单下拉框", | ||||
|           "fixedLabel": "单下拉框", | ||||
|           "grid": 0.5, | ||||
|           "fieldTips": "请选择", | ||||
|           "icon": "iconSelect", | ||||
|           "mustFill": "1", | ||||
|           "defaultValue": "", | ||||
|           "disable": "0", | ||||
|           "options": [ | ||||
|             { | ||||
|               "label": "选项1", | ||||
|               "value": "" | ||||
|             }, | ||||
|             { | ||||
|               "label": "选项2", | ||||
|               "value": "" | ||||
|             } | ||||
|           ], | ||||
|           "title": "" | ||||
|         }, | ||||
|         { | ||||
|           "type": "onOff", | ||||
|           "fieldName": "开关", | ||||
|           "fixedLabel": "开关", | ||||
|           "grid": 0.5, | ||||
|           "fieldTips": "请选择开关", | ||||
|           "icon": "iconSelect", | ||||
|           "mustFill": "1", | ||||
|           "defaultValue": "0", | ||||
|           "disable": "0", | ||||
|           "title": "" | ||||
|         }, | ||||
|         { | ||||
|           "type": "date", | ||||
|           "fieldName": "日期", | ||||
|           "fixedLabel": "日期", | ||||
|           "grid": 0.5, | ||||
|           "datetimePattern": "yyyy-MM-dd", | ||||
|           "fieldTips": "请选择日期", | ||||
|           "icon": "iconSelect", | ||||
|           "mustFill": "1", | ||||
|           "disable": "0", | ||||
|           "title": "" | ||||
|         }, | ||||
|         { | ||||
|           "type": "time", | ||||
|           "fieldName": "时间", | ||||
|           "fixedLabel": "时间", | ||||
|           "grid": 0.5, | ||||
|           "datetimePattern": "HH:mm:ss", | ||||
|           "fieldTips": "请选择时间", | ||||
|           "icon": "iconSelect", | ||||
|           "mustFill": "1", | ||||
|           "disable": "0", | ||||
|           "title": "" | ||||
|         }, | ||||
|         { | ||||
|           "type": "datetime", | ||||
|           "fieldName": "日期时间", | ||||
|           "fixedLabel": "日期时间", | ||||
|           "grid": 0.5, | ||||
|           "datetimePattern": "yyyy-MM-dd HH:mm:ss", | ||||
|           "fieldTips": "请选择日期时间", | ||||
|           "icon": "iconSelect", | ||||
|           "mustFill": "1", | ||||
|           "disable": "0", | ||||
|           "title": "" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "type": "input", | ||||
|       "tips": "(可重复添加)", | ||||
|       "label": "填空", | ||||
|       "children": [ | ||||
|         { | ||||
|           "type": "input", | ||||
|           "fieldName": "单行填空", | ||||
|           "fieldTips": "请输入", | ||||
|           "fixedLabel": "单行填空", | ||||
|           "disable": "0", | ||||
|           "grid": 0.5, | ||||
|           "defaultValue": "", | ||||
|           "icon": "icontext_box", | ||||
|           "mustFill": "1", | ||||
|           "maxLength": 50 | ||||
|         }, | ||||
|         { | ||||
|           "type": "textarea", | ||||
|           "fieldName": "多行填空", | ||||
|           "fixedLabel": "多行填空", | ||||
|           "fieldTips": "请输入", | ||||
|           "lineNumber": 4, | ||||
|           "defaultValue": "", | ||||
|           "icon": "icontext_area", | ||||
|           "mustFill": "1", | ||||
|           "maxLength": 500, | ||||
|           "disable": "0", | ||||
|           "grid": 1 | ||||
|         }, | ||||
|         { | ||||
|           "type": "number", | ||||
|           "fieldName": "数字输入", | ||||
|           "fixedLabel": "数字输入", | ||||
|           "fieldTips": "请输入数字", | ||||
|           "defaultValue": "", | ||||
|           "icon": "icontext_area", | ||||
|           "mustFill": "1", | ||||
|           "maxValue": 10000, | ||||
|           "decimalPlaces": 0, | ||||
|           "minValue": 0, | ||||
|           "maxLength": 500, | ||||
|           "disable": "0", | ||||
|           "grid": 0.5 | ||||
|         }, | ||||
|         { | ||||
|           "type": "rtf", | ||||
|           "fieldName": "富文本", | ||||
|           "fixedLabel": "富文本", | ||||
|           "fieldTips": "请输入", | ||||
|           "defaultValue": "", | ||||
|           "icon": "icontext_area", | ||||
|           "mustFill": "1", | ||||
|           "maxLength": 5000, | ||||
|           "disable": "0", | ||||
|           "grid": 1 | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "type": "annex", | ||||
|       "tips": "(可重复添加)", | ||||
|       "label": "附件", | ||||
|       "children": [ | ||||
|         { | ||||
|           "type": "upload", | ||||
|           "fieldTips": "请上传", | ||||
|           "fieldName": "上传附件", | ||||
|           "fixedLabel": "上传附件", | ||||
|           "disable": "0", | ||||
|           "fileChoseSize": 10, | ||||
|           "fileMaxCount": 9, | ||||
|           "defaultValue": "", | ||||
|           "icon": "iconpic", | ||||
|           "mustFill": "1", | ||||
|           "grid": 1 | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "type": "layout", | ||||
|       "tips": "(可重复添加)", | ||||
|       "label": "分组", | ||||
|       "children": [ | ||||
|         { | ||||
|           "type": "group", | ||||
|           "fieldName": "卡片", | ||||
|           "fixedLabel": "卡片", | ||||
|           "icon": "iconpic", | ||||
|           "groupName": "分组标题", | ||||
|           "column": [] | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										1049
									
								
								project/oms/apps/develop/AppAiCode/detailLayout.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1049
									
								
								project/oms/apps/develop/AppAiCode/detailLayout.vue
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -14,6 +14,14 @@ | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :total="page.total" :current.sync="page.current" :size.sync="page.size" | ||||
|                   @getList="getTableData" :col-configs="colConfigs" :dict="dict"> | ||||
|           <el-table-column type="expand" slot="expand"> | ||||
|             <template slot-scope="{row}"> | ||||
|               <ai-wrapper> | ||||
|                 <ai-info-item labelWidth="200px" v-for="op in desConfigs" :key="op.prop" :value="row[op.prop]" | ||||
|                               v-bind="op"/> | ||||
|               </ai-wrapper> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|           <el-table-column slot="process" label="打包进度"> | ||||
|             <template slot-scope="{row}"> | ||||
|               <span v-if="row.count==0" v-text="getProcessMsg(row)"/> | ||||
| @@ -24,27 +32,40 @@ | ||||
|             <template slot-scope="{row}"> | ||||
|               <el-button type="text" @click="handleEdit(row)">编辑</el-button> | ||||
|               <el-button type="text" @click="handleDelete(row.id)">删除</el-button> | ||||
|               <el-button type="text" @click="handleZip(row)">打包更新</el-button> | ||||
|               <el-button type="text" v-if="row.download&&row.target" @click="handleDownload(row)">下载</el-button> | ||||
|               <el-button type="text" @click="handleZip(row)" v-if="row.count==0">打包更新</el-button> | ||||
|               <el-button type="text" @click="handleCancelZip(row)" v-else>停止打包</el-button> | ||||
|               <el-button type="text" v-if="row.target" @click="handleDownload(row)">下载</el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <ai-dialog :visible.sync="dialog" title="部署任务设置" width="700px" @close="form={}" @onConfirm="submit"> | ||||
|       <el-form ref="DialogForm" :model="form" size="small" label-width="120px" :rules="rules"> | ||||
|       <el-form ref="DialogForm" :model="form" size="small" label-width="100px" :rules="rules"> | ||||
|         <el-form-item label="项目/系统" prop="name"> | ||||
|           <el-input v-model="form.name" clearable placeholder="请输入"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="系统类型" prop="type"> | ||||
|           <ai-select v-model="form.type" :selectList="dict.getDict('systemType')"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="打包脚本" prop="libShell"> | ||||
|           <el-input v-model="form.libShell" clearable placeholder="请输入"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="更新脚本" prop="updateShell"> | ||||
|           <el-input v-model="form.updateShell" clearable placeholder="请输入"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="开发环境nginx" prop="target"> | ||||
|         <el-form-item label="项目URL" prop="webUrl"> | ||||
|           <el-input v-model="form.webUrl" clearable placeholder="请输入"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="打包地址" prop="webUrl"> | ||||
|           <el-input v-model="form.zipPath" clearable placeholder="请输入"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="nginx路径" prop="target"> | ||||
|           <el-input v-model="form.target" clearable placeholder="请输入"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="node版本" prop="nodeVersion"> | ||||
|           <el-input v-model="form.nodeVersion" clearable placeholder="请输入"/> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| @@ -62,7 +83,18 @@ export default { | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']) | ||||
|     ...mapState(['user']), | ||||
|     desConfigs() { | ||||
|       let isLine = true | ||||
|       return [ | ||||
|         {prop: "libShell", label: "打包脚本", width: 100}, | ||||
|         {prop: "updateShell", label: "更新脚本", width: 100}, | ||||
|         {prop: "zipPath", label: "打包地址", width: 100, isLine}, | ||||
|         {prop: "target", label: "nginx路径", width: 100, isLine}, | ||||
|         {prop: "webUrl", label: "项目URL", width: 100}, | ||||
|         {prop: "nodeVersion", label: "node打包版本", width: 100}, | ||||
|       ] | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
| @@ -70,10 +102,10 @@ export default { | ||||
|       page: {current: 1, size: 10, total: 0}, | ||||
|       tableData: [], | ||||
|       colConfigs: [ | ||||
|         {slot: "expand"}, | ||||
|         {label: "项目/系统名称", prop: "name", width: 200}, | ||||
|         {label: "打包脚本", prop: "libShell"}, | ||||
|         {label: "更新脚本", prop: "updateShell"}, | ||||
|         {label: "nginx地址", prop: "target"}, | ||||
|         {label: "系统类型", prop: "type", dict: "systemType", width: 80}, | ||||
|         {label: "nginx路径", prop: "target"}, | ||||
|         {slot: "process"}, | ||||
|         {slot: "options"} | ||||
|       ], | ||||
| @@ -81,9 +113,8 @@ export default { | ||||
|       form: {}, | ||||
|       rules: { | ||||
|         name: {required: true, message: "请输入项目/系统名称"}, | ||||
|         libShell: {required: true, message: "请输入 打包脚本"}, | ||||
|         updateShell: {required: true, message: "请输入 更新脚本"}, | ||||
|       } | ||||
|       }, | ||||
|       timer: {} | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
| @@ -118,29 +149,28 @@ export default { | ||||
|       }) | ||||
|     }, | ||||
|     handleZip(row) { | ||||
|       let {id} = row | ||||
|       let {id} = row, {timer} = this | ||||
|       this.instance.post("/node/autodeploy/getZip", null, { | ||||
|         params: {id} | ||||
|       }).then(res => { | ||||
|         if (res?.code == 0) { | ||||
|           row.count = 1 | ||||
|           let timer = setInterval(() => { | ||||
|           timer[id] = setInterval(() => { | ||||
|             if (row.count >= 100) { | ||||
|               clearInterval(timer) | ||||
|               clearInterval(timer[id]) | ||||
|               row.count = 0 | ||||
|               this.$message.error("打包失败!") | ||||
|             } else if (row.count <= 20 && row.target) { | ||||
|             } else if (row.count <= 10 && row.target) { | ||||
|               row.count++ | ||||
|             } else this.handleConfirmZip(row).then(v => { | ||||
|               if (v.error) { | ||||
|                 clearInterval(timer) | ||||
|                 clearInterval(timer[id]) | ||||
|                 this.$message.error("打包失败!") | ||||
|                 row.download = v.download | ||||
|                 row.error = v.error | ||||
|                 this.refreshRow(row, v) | ||||
|                 row.count = 0 | ||||
|               } else if (v.download) { | ||||
|                 clearInterval(timer) | ||||
|                 row.download = v.download | ||||
|                 row.error = v.error | ||||
|                 clearInterval(timer[id]) | ||||
|                 this.refreshRow(row, v) | ||||
|                 row.count = 0 | ||||
|               } else row.count++ | ||||
|             }) | ||||
| @@ -148,6 +178,23 @@ export default { | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     refreshRow(row, v) { | ||||
|       row.error = v.error | ||||
|       row.download = v.download | ||||
|       row.zipTime = v.zipTime | ||||
|     }, | ||||
|     handleCancelZip(row) { | ||||
|       let {id} = row | ||||
|       return this.instance.post("/node/autodeploy/cancelZip", null, { | ||||
|         params: {id} | ||||
|       }).then(res => { | ||||
|         if (res?.code == 0) { | ||||
|           clearInterval(this.timer[id]) | ||||
|           row.count = 0 | ||||
|           this.handleConfirmZip(row).then(v => this.refreshRow(row, v)) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleEdit(row) { | ||||
|       this.form = JSON.parse(JSON.stringify(row)) | ||||
|       this.dialog = true | ||||
| @@ -186,11 +233,17 @@ export default { | ||||
|       }) | ||||
|     }, | ||||
|     getProcessMsg(row) { | ||||
|       return row.error || (row.download ? `最近打包时间:${row.download}` : `暂无打包`) | ||||
|       let time = row.zipTime ? this.$moment(row.download).diff(row.zipTime, 's', true) : "" | ||||
|       return row.error || (row.download ? `最近打包时间:${row.download}(用时:${time}秒)` : | ||||
|           row.zipTime ? `正在打包,开始于:${row.zipTime}` : `暂无打包`) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load("systemType") | ||||
|     this.getTableData() | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     Object.values(this.timer).map(t => clearInterval(t)) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @@ -228,5 +228,6 @@ export default { | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .AppDeployWxmp { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										66
									
								
								project/oms/apps/develop/AppForm/AppForm.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								project/oms/apps/develop/AppForm/AppForm.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| <template> | ||||
|   <div class="doc-circulation"> | ||||
|     <keep-alive :include="['List']"> | ||||
|       <component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"/> | ||||
|     </keep-alive> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import List from './components/List' | ||||
|   import Add from './components/Add' | ||||
|  | ||||
|   export default { | ||||
|     name: 'AppForm', | ||||
|     label: '配置表单', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         component: 'List', | ||||
|         params: {}, | ||||
|         include: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       Add, | ||||
|       List | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onChange (data) { | ||||
|         if (data.type === 'Add') { | ||||
|           this.component = 'Add' | ||||
|           this.params = data.params | ||||
|         } | ||||
|  | ||||
|         if (data.type === 'list') { | ||||
|           this.component = 'List' | ||||
|           this.params = data.params | ||||
|  | ||||
|           this.$nextTick(() => { | ||||
|             if (data.isRefresh) { | ||||
|               this.$refs.component.getList() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
|   .doc-circulation { | ||||
|     height: 100%; | ||||
|     background: #F3F6F9; | ||||
|     overflow: auto; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										281
									
								
								project/oms/apps/develop/AppForm/components/Add.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								project/oms/apps/develop/AppForm/components/Add.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,281 @@ | ||||
| <template> | ||||
|   <ai-detail class="form-add" :class="[currIndex === 1 ? 'form-add__active' : '']"> | ||||
|     <ai-title title="表单配置" slot="title" isShowBottomBorder isShowBack  @onBackClick="cancel(false)"></ai-title> | ||||
|     <template #content> | ||||
|       <div class="ai-step"> | ||||
|         <div class="ai-step__item" | ||||
|           :class="[currIndex >= index ? 'ai-step__item--active' : '']" | ||||
|           v-for="(item, index) in statusList" | ||||
|           :key="index"> | ||||
|           <div class="ai-step__item--icon" v-if="currIndex <= index"> | ||||
|             <i v-if="currIndex === index"></i> | ||||
|           </div> | ||||
|           <div class="el-icon-success" v-if="currIndex > index"> | ||||
|           </div> | ||||
|           <span>{{ item }}</span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <basic-info ref="basicInfo" v-model="basicInfo" v-show="currIndex === 0" :dict="dict" :instance="instance"></basic-info> | ||||
|       <form-layout :appType="basicInfo.appType" :currIndex="currIndex" class="form-config__wrapper" v-model="tableInfos" ref="form" v-show="currIndex === 1" :dict="dict" :instance="instance"></form-layout> | ||||
|       <form-config | ||||
|         ref="config" | ||||
|         :showListFields="showListFields" | ||||
|         :btns="btns" | ||||
|         :fuzzyQueryFields="fuzzyQueryFields" | ||||
|         :tableInfos="tableInfos" | ||||
|         :orderFields="orderFields" | ||||
|         v-if="currIndex === 2"> | ||||
|       </form-config> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button @click="cancel">取消</el-button> | ||||
|       <el-button @click="back" v-if="currIndex > 0">上一步</el-button> | ||||
|       <el-button @click="next" type="primary">{{ currIndex === 2 ? '完成' : '下一步' }}</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import BasicInfo from './BasicInfo.vue' | ||||
|   import FormLayout from './FormLayout.vue' | ||||
|   import FormConfig from './FormConfig.vue' | ||||
|   export default { | ||||
|     name: 'add', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       params: Object, | ||||
|       type: String | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       FormLayout, | ||||
|       BasicInfo, | ||||
|       FormConfig | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         currIndex: 0, | ||||
|         basicInfo: { | ||||
|           saasPlatformId: '', | ||||
|           menuLeve1Style: '', | ||||
|           saasPlatformName: '', | ||||
|           menuLevel1Name: '', | ||||
|           menuLevel3Name: '', | ||||
|           menuLevel2Name: '', | ||||
|           appType: '' | ||||
|         }, | ||||
|         orderFields: [], | ||||
|         showListFields: [], | ||||
|         fuzzyQueryFields: [], | ||||
|         btns: [], | ||||
|         btnKeys: ['insertEnable', 'importEnable', 'exportEnalbe', 'editEnable', 'deleteEnable', 'batchDelEnable'], | ||||
|         configInfo: { | ||||
|           btns: [], | ||||
|           orderType: '0', | ||||
|           fieldName: '' | ||||
|         }, | ||||
|         info: {}, | ||||
|         tableInfos: [], | ||||
|         statusList: ['基础设置', '表单设计', '列表设计'] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       if (this.params.id) { | ||||
|         this.getInfo() | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       cancel (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'list', | ||||
|           isRefresh: isRefresh ? true : false, | ||||
|           isQuote: this.params.isQuote ? true : false | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       confirm () { | ||||
|  | ||||
|       }, | ||||
|  | ||||
|       back () { | ||||
|         this.currIndex = this.currIndex - 1 | ||||
|       }, | ||||
|  | ||||
|       confirmBasicInfo () { | ||||
|         return this.$refs.basicInfo.validate() | ||||
|       }, | ||||
|  | ||||
|       getInfo () { | ||||
|         this.instance.post(`/app/appapplicationinfo/queryDetailById?id=${this.params.id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.info = res.data | ||||
|             this.basicInfo = { | ||||
|               saasPlatformId: res.data.saasPlatformId, | ||||
|               menuLeve1Style: res.data.menuLeve1Style, | ||||
|               saasPlatformName: res.data.saasPlatformName, | ||||
|               menuLevel1Name: res.data.menuLevel1Name, | ||||
|               menuLevel3Name: res.data.menuLevel3Name, | ||||
|               menuLevel2Name: res.data.menuLevel2Name, | ||||
|               appType: res.data.appType, | ||||
|               corpId: res.data.corpId, | ||||
|               corpName: res.data.corpName | ||||
|             } | ||||
|             this.fuzzyQueryFields = res.data.fuzzyQueryFields | ||||
|             this.tableInfos = res.data.tableInfos | ||||
|             this.showListFields = res.data.showListFields | ||||
|             this.orderFields = res.data.orderFields | ||||
|             this.btns = Object.keys(res.data).filter(v => { | ||||
|               return this.btnKeys.indexOf(v) > -1 && res.data[v] === '1' | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       submit (info) { | ||||
|         this.instance.post(`/app/appapplicationinfo/addOrUpdate`, { | ||||
|           ...this.info, | ||||
|           ...this.basicInfo, | ||||
|           tableInfos: this.tableInfos, | ||||
|           ...info.btns, | ||||
|           id: this.params.id, | ||||
|           applicationName: this.basicInfo.menuLevel3Name || this.basicInfo.menuLevel2Name, | ||||
|           fuzzyQueryFields: info.fuzzyQueryFields, | ||||
|           orderType: info.orderType, | ||||
|           orderFields: info.orderFields, | ||||
|           showListFields: info.showListFields | ||||
|         }).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.$message.success(this.params.id ? '编辑成功' : '添加成功') | ||||
|             this.cancel(true) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       next () { | ||||
|         if (this.currIndex === 0) { | ||||
|           if (!this.$refs.basicInfo.validate()) return | ||||
|         } | ||||
|  | ||||
|         if (this.currIndex === 1) { | ||||
|           this.$refs.form.onConfirm() | ||||
|         } | ||||
|  | ||||
|         if (this.currIndex === 2) { | ||||
|           const info = this.$refs.config.validate() | ||||
|           if (!info) return | ||||
|  | ||||
|           this.submit(info) | ||||
|  | ||||
|           return false | ||||
|         } | ||||
|  | ||||
|         this.currIndex = this.currIndex + 1 | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .form-add { | ||||
|     &.form-add__active { | ||||
|       ::v-deep .ai-detail__content--wrapper { | ||||
|         max-width: 100%!important; | ||||
|         height: 100%!important; | ||||
|         background: #F5F6F9; | ||||
|       } | ||||
|  | ||||
|       .form-config__wrapper { | ||||
|         height: calc(100% - 52px); | ||||
|         overflow-y: hidden; | ||||
|       } | ||||
|  | ||||
|       ::v-deep .ai-detail__content { | ||||
|         height: calc(100% - 114px)!important; | ||||
|         padding: 0!important; | ||||
|         overflow: hidden!important; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .ai-step { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: center; | ||||
|       margin-top: 4px; | ||||
|       margin-bottom: 24px; | ||||
|  | ||||
|       .ai-step__item { | ||||
|         display: flex; | ||||
|         position: relative; | ||||
|         align-items: center; | ||||
|         margin-right: 216px; | ||||
|  | ||||
|         &.ai-step__item--active { | ||||
|           span { | ||||
|             color: #2266FF; | ||||
|           } | ||||
|  | ||||
|           .ai-step__item--icon { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|             border-color: #2266FF; | ||||
|  | ||||
|             i { | ||||
|               width: 12px; | ||||
|               height: 12px; | ||||
|               border-radius: 50%; | ||||
|               background: #2266FF; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         &:after { | ||||
|           position: absolute; | ||||
|           top: 50%; | ||||
|           right: -208px; | ||||
|           width: 200px; | ||||
|           height: 2px; | ||||
|           background: #D0D4DC; | ||||
|           content: ' '; | ||||
|           transform: translateY(-50%); | ||||
|         } | ||||
|  | ||||
|         &:last-child { | ||||
|           margin-right: 0; | ||||
|  | ||||
|           &::after { | ||||
|             display: none; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .ai-step__item--icon { | ||||
|           width: 24px; | ||||
|           height: 24px; | ||||
|           margin-right: 8px; | ||||
|           border-radius: 50%; | ||||
|           background: #FFFFFF; | ||||
|           border: 2px solid #D0D4DC; | ||||
|         } | ||||
|  | ||||
|         .el-icon-success { | ||||
|           width: 24px; | ||||
|           height: 24px; | ||||
|           font-size: 24px; | ||||
|           margin-right: 8px; | ||||
|           color: #2266FF; | ||||
|           border-radius: 50%; | ||||
|         } | ||||
|  | ||||
|         span { | ||||
|           color: #666666; | ||||
|           font-size: 14px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										151
									
								
								project/oms/apps/develop/AppForm/components/BasicInfo.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								project/oms/apps/develop/AppForm/components/BasicInfo.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,151 @@ | ||||
| <template> | ||||
|   <div class="basicInfo"> | ||||
|     <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|       <ai-card title="基本信息"> | ||||
|         <template #content> | ||||
|           <div class="ai-form"> | ||||
|             <el-form-item label="所属平台" prop="saasPlatformId" style="width: 100%;" :rules="[{ required: true, message: '请选择所属平台', trigger: 'change' }]"> | ||||
|               <el-select | ||||
|                 size="small" | ||||
|                 style="width: 100%;" | ||||
|                 placeholder="请选择所属平台" | ||||
|                 clearable | ||||
|                 @change="onChange" | ||||
|                 v-model="form.saasPlatformId"> | ||||
|                 <el-option | ||||
|                   v-for="(item, index) in sassList" | ||||
|                   :key="index" | ||||
|                   :label="item.name" | ||||
|                   :value="item.id"> | ||||
|                 </el-option> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item v-if="form.saasPlatformId" style="width: 100%;" label="所属企业" prop="corpId" :rules="[{ required: true, message: '请选择所属企业', trigger: 'change' }]"> | ||||
|               <ai-select | ||||
|                 v-model="form.corpId" | ||||
|                 placeholder="请选择所属企业" | ||||
|                 clearable | ||||
|                 @change="onCompanyChange" | ||||
|                 :selectList="companyList"> | ||||
|               </ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item  style="width: 100%;" label="一级菜单名称" prop="menuLevel1Name" :rules="[{ required: true, message: '请输入一级菜单名称', trigger: 'change' }]"> | ||||
|               <el-input size="small" placeholder="请输入一级菜单名称" :maxlength="8" v-model="form.menuLevel1Name"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%;" label="二级菜单名称" prop="menuLevel2Name" :rules="[{ required: true, message: '请输入二级菜单名称', trigger: 'change' }]"> | ||||
|               <el-input size="small" placeholder="请输入二级菜单名称" :maxlength="8" v-model="form.menuLevel2Name"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%;" label="三级菜单名称" prop="menuLevel3Name"> | ||||
|               <el-input size="small" placeholder="请输入三级菜单名称" :maxlength="8" v-model="form.menuLevel3Name"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%;" label="应用类型" prop="appType"> | ||||
|               <ai-select | ||||
|                 v-model="form.appType" | ||||
|                 placeholder="请选择应用类型" | ||||
|                 clearable | ||||
|                 :selectList="dict.getDict('diyAppType')"> | ||||
|               </ai-select> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|     </el-form> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'basicInfo', | ||||
|  | ||||
|     model: { | ||||
|       prop: 'value', | ||||
|       event: 'change', | ||||
|     }, | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       value: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         form: { | ||||
|           saasPlatformId: '', | ||||
|           menuLeve1Style: '', | ||||
|           saasPlatformName: '', | ||||
|           menuLevel1Name: '', | ||||
|           menuLevel2Name: '', | ||||
|           menuLevel3Name: '', | ||||
|           appType: '', | ||||
|           corpId: '', | ||||
|           corpName: '' | ||||
|         }, | ||||
|         companyList: [], | ||||
|         sassList: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     watch: { | ||||
|       value (v) { | ||||
|         this.form = JSON.parse(JSON.stringify(v)) | ||||
|         if (this.form.saasPlatformId) { | ||||
|           this.getCompanyList() | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.dict.load('diyAppType') | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.getSassList() | ||||
|       this.form = JSON.parse(JSON.stringify(this.value)) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onChange (e) { | ||||
|         this.form.saasPlatformName = this.sassList.filter(v => v.id === e)[0].name | ||||
|         this.form.saasPlatformId && this.getCompanyList() | ||||
|       }, | ||||
|  | ||||
|       validate () { | ||||
|         let result = false | ||||
|         this.$refs.form.validate(valid => { | ||||
|           result = valid | ||||
|         }) | ||||
|         this.$emit('change', this.form) | ||||
|         return result  | ||||
|       }, | ||||
|  | ||||
|       onCompanyChange (e) { | ||||
|         this.form.corpName = this.companyList.filter(v => v.dictValue === e)[0].dictName | ||||
|       }, | ||||
|  | ||||
|       getCompanyList () { | ||||
|         this.instance.post(`/app/appCorp/page?current=1&size=1000&saasId=${this.form.saasPlatformId}`).then(res => { | ||||
|           if (res.data.records.length) { | ||||
|             this.companyList = res.data.records.map(v => { | ||||
|               return { | ||||
|                 dictValue: v.corpId, | ||||
|                 dictName: v.name | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getSassList () { | ||||
|         this.instance.post(`/app/appSaas/listAll`).then(res => { | ||||
|           if (res.data) { | ||||
|             this.sassList = res.data | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| </style> | ||||
							
								
								
									
										244
									
								
								project/oms/apps/develop/AppForm/components/FormConfig.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								project/oms/apps/develop/AppForm/components/FormConfig.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,244 @@ | ||||
| <template> | ||||
|   <div class="basicInfo"> | ||||
|     <ai-card title="搜索字段" class="search-wrapper"> | ||||
|       <template #content> | ||||
|         <el-checkbox-group v-model="queryFields"> | ||||
|           <el-checkbox | ||||
|             :label="`${item.fieldDbName}~${item.fieldName}`" | ||||
|             v-for="(item, index) in tableInfos" | ||||
|             :key="index"> | ||||
|             {{ item.fieldName }} | ||||
|           </el-checkbox> | ||||
|         </el-checkbox-group> | ||||
|       </template> | ||||
|     </ai-card> | ||||
|     <ai-card title="表格字段"> | ||||
|       <template #content> | ||||
|         <div class="ai-table"> | ||||
|           <div class="el-table el-table--border ai-header__border"> | ||||
|             <el-scrollbar> | ||||
|               <table cellspacing="0" cellpadding="0" border="0" class="el-table__body"> | ||||
|                 <draggable element="thead" animation="500" class="el-table__header is-leaf ai-table__header" :sort="true" v-model="showFields"> | ||||
|                   <th v-for="(item, index) in showFields" style="background: #f3f4f5; text-align: center;" class="ai-table__header" :key="index">{{ item.fieldName }}</th> | ||||
|                 </draggable>  | ||||
|                 <tbody element="tbody"> | ||||
|                   <tr> | ||||
|                     <td @click="handleShow(index, item.isShow)" v-for="(item, index) in showFields" :key="index">{{ item.isShow ? '已显示' : '已隐藏' }}</td> | ||||
|                   </tr> | ||||
|                 </tbody>  | ||||
|               </table> | ||||
|             </el-scrollbar> | ||||
|           </div> | ||||
|         </div> | ||||
|       </template> | ||||
|     </ai-card> | ||||
|     <ai-card title="排序和操作按钮"> | ||||
|       <template #content> | ||||
|         <el-form ref="form" class="ai-form" :model="form" label-width="110px" label-position="right"> | ||||
|           <el-form-item label="排序字段" prop="field"> | ||||
|             <el-select | ||||
|               size="small" | ||||
|               placeholder="默认按创建时间排序" | ||||
|               clearable | ||||
|               v-model="form.field"> | ||||
|               <el-option | ||||
|                 v-for="(filed, index) in tableInfos" | ||||
|                 :key="index" | ||||
|                 :label="filed.fieldName" | ||||
|                 :value="`${filed.fieldDbName}~${filed.fieldName}`"> | ||||
|               </el-option> | ||||
|             </el-select> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="排序类型" prop="orderType" :rules="[{ required: true, message: '请输入排序类型', trigger: 'change' }]"> | ||||
|             <el-radio-group v-model="form.orderType"> | ||||
|               <el-radio label="asc">升序</el-radio> | ||||
|               <el-radio label="desc">降序</el-radio> | ||||
|             </el-radio-group> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="按钮配置" prop="btns" style="width: 100%;" :rules="[{ required: true, message: '请输入按钮配置', trigger: 'change' }]"> | ||||
|             <el-checkbox-group v-model="form.btns"> | ||||
|               <el-checkbox label="insertEnable">添加</el-checkbox> | ||||
|               <el-checkbox label="importEnable">导入</el-checkbox> | ||||
|               <el-checkbox label="exportEnalbe">导出</el-checkbox> | ||||
|               <el-checkbox label="editEnable">编辑</el-checkbox> | ||||
|               <el-checkbox label="deleteEnable">删除</el-checkbox> | ||||
|               <el-checkbox label="batchDelEnable">批量删除</el-checkbox> | ||||
|             </el-checkbox-group> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </template> | ||||
|     </ai-card> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import draggable from 'vuedraggable' | ||||
|   export default { | ||||
|     name: 'configForm', | ||||
|  | ||||
|     props: { | ||||
|       tableInfos: Array, | ||||
|       btns: Array, | ||||
|       showListFields: Array, | ||||
|       orderFields: Array, | ||||
|       fuzzyQueryFields: Array | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       draggable | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         queryFields: [], | ||||
|         tableData: [{}], | ||||
|         btnKeys: ['insertEnable', 'importEnable', 'exportEnalbe', 'editEnable', 'deleteEnable', 'batchDelEnable'], | ||||
|         form: { | ||||
|           btns: [], | ||||
|           orderType: 'asc', | ||||
|           field: '' | ||||
|         }, | ||||
|         showFields: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       const showIds = this.showListFields.map(v => v.fieldDbName) | ||||
|       this.showFields = JSON.parse(JSON.stringify(this.tableInfos)).map(item => { | ||||
|         item.isShow = showIds.indexOf(item.fieldDbName) > -1 ? true : false | ||||
|  | ||||
|         return item | ||||
|       }) | ||||
|  | ||||
|       if (!this.showListFields.length) { | ||||
|         this.showFields.map(v => { | ||||
|           v.isShow = true | ||||
|           return v | ||||
|         }) | ||||
|       } | ||||
|  | ||||
|       this.tableInfos.map(item => { | ||||
|         this.tableData[0][item.fieldDbName] = '删除' | ||||
|       }) | ||||
|  | ||||
|       if (this.btns.length) { | ||||
|         this.form.btns = this.btns | ||||
|       } | ||||
|  | ||||
|       const tableInfosIds = this.tableInfos.map(v => v.fieldDbName) | ||||
|  | ||||
|       if (this.orderFields.length) { | ||||
|         let arr = this.orderFields.filter(v => { | ||||
|           return tableInfosIds.indexOf(v.fieldDbName) > -1 | ||||
|         }).map(item => { | ||||
|           return `${item.fieldDbName}~${item.fieldName}` | ||||
|         }) | ||||
|  | ||||
|         if (arr.length) { | ||||
|           this.form.field = arr[0] | ||||
|         } | ||||
|       } | ||||
|       if (this.fuzzyQueryFields.length) { | ||||
|         this.queryFields = this.fuzzyQueryFields.filter(v => { | ||||
|           return tableInfosIds.indexOf(v.fieldDbName) > -1 | ||||
|         }).map(item => { | ||||
|           return `${item.fieldDbName}~${item.fieldName}` | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       validate () { | ||||
|         let result = false | ||||
|         this.$refs.form.validate(valid => { | ||||
|           result = valid | ||||
|         }) | ||||
|  | ||||
|         if (!result) { | ||||
|           return false | ||||
|         } | ||||
|  | ||||
|         const btns = {} | ||||
|         this.btnKeys.forEach(item => { | ||||
|           btns[item] = this.form.btns.indexOf(item) > -1 ? 1 : 0  | ||||
|         }) | ||||
|  | ||||
|         return { | ||||
|           btns, | ||||
|           orderFields: [{ | ||||
|             fieldName: this.form.field.split('~')[1], | ||||
|             fieldDbName: this.form.field.split('~')[0], | ||||
|             orderType: this.form.orderType | ||||
|           }], | ||||
|           showListFields: this.showFields.filter(v => v.isShow).map((v, index) => { | ||||
|             return { | ||||
|               fieldName: v.fieldName, | ||||
|               fieldDbName: v.fieldDbName, | ||||
|               showListIndex: index | ||||
|             } | ||||
|           }), | ||||
|           fuzzyQueryFields: this.queryFields.map(v => { | ||||
|             return { | ||||
|               fieldName: v.split('~')[1], | ||||
|               fieldDbName: v.split('~')[0] | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       handleShow (index, isShow) { | ||||
|         const total = this.showFields.map(v => v.isShow).filter(v => !!v) | ||||
|         if (total.length <= 1 && isShow) { | ||||
|           return this.$message.error('表格列数不能小于1') | ||||
|         } | ||||
|  | ||||
|         this.$set(this.showFields[index], 'isShow', !isShow) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .basicInfo { | ||||
|     .search-wrapper { | ||||
|       ::v-deep .el-checkbox-group { | ||||
|         display: flex; | ||||
|         flex-wrap: wrap; | ||||
|  | ||||
|         .el-checkbox { | ||||
|           width: 16.66%; | ||||
|           margin-bottom: 10px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .ai-table { | ||||
|     .el-table--border { | ||||
|       border: 1px solid #d0d4dc; | ||||
|       border-bottom: none; | ||||
|       border-right: none; | ||||
|     } | ||||
|     table { | ||||
|       min-width: 100%; | ||||
|     } | ||||
|  | ||||
|     th, tr { | ||||
|       min-width: 100px; | ||||
|       cursor: move; | ||||
|     } | ||||
|  | ||||
|     tr { | ||||
|       td { | ||||
|         cursor: pointer; | ||||
|         color: #26f; | ||||
|         text-align: center; | ||||
|         user-select: none; | ||||
|  | ||||
|         &:hover { | ||||
|           opacity: 0.7; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										1198
									
								
								project/oms/apps/develop/AppForm/components/FormLayout.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1198
									
								
								project/oms/apps/develop/AppForm/components/FormLayout.vue
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										272
									
								
								project/oms/apps/develop/AppForm/components/config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								project/oms/apps/develop/AppForm/components/config.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,272 @@ | ||||
| export const components = [ | ||||
| 	{ | ||||
| 		type: 'info', | ||||
| 		tips: '(不能重复添加同一元素)', | ||||
| 		label: '信息', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'name', | ||||
| 				fieldName: '姓名', | ||||
| 				fieldTips: '请输入姓名', | ||||
| 				fixedLabel: '姓名', | ||||
| 				disable: '0', | ||||
| 				grid: 0.5, | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_box', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 20 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'idNumber', | ||||
| 				fieldName: '身份证号', | ||||
| 				fixedLabel: '身份证号', | ||||
| 				fieldTips: '请输入身份证号', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 20, | ||||
| 				disable: '0', | ||||
| 				grid: 0.5 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'phone', | ||||
| 				fieldName: '联系方式', | ||||
| 				fixedLabel: '联系方式', | ||||
| 				fieldTips: '请输入联系方式', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 20, | ||||
| 				disable: '0', | ||||
| 				grid: 0.5 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'area', | ||||
| 				fieldName: '地区', | ||||
| 				fixedLabel: '地区', | ||||
| 				fieldTips: '请选择地区', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				areaPattern: '', | ||||
| 				disable: '0', | ||||
| 				grid: 0.5 | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	{ | ||||
| 		type: 'options', | ||||
| 		tips: '(可重复添加)', | ||||
| 		label: '选项', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'radio', | ||||
| 				fieldName: '单选', | ||||
| 				fixedLabel: '单选', | ||||
| 				fieldTips: '请选择', | ||||
| 				grid: 0.5, | ||||
| 				icon: 'iconradio', | ||||
| 				mustFill: '1', | ||||
| 				disable: '0', | ||||
| 				defaultValue: '', | ||||
| 				options: [ | ||||
| 					{ | ||||
| 						label: '选项1', | ||||
| 						value: '' | ||||
| 					}, | ||||
| 					{ | ||||
| 						label: '选项2', | ||||
| 						value: '' | ||||
| 					} | ||||
| 				], | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'checkbox', | ||||
| 				fieldName: '多选', | ||||
| 				fixedLabel: '多选', | ||||
| 				fieldTips: '请选择', | ||||
| 				icon: 'iconcheck_box', | ||||
| 				mustFill: '1', | ||||
| 				grid: 0.5, | ||||
| 				disable: '0', | ||||
| 				defaultValue: [], | ||||
| 				options: [ | ||||
| 					{ | ||||
| 						label: '选项1', | ||||
| 						value: '' | ||||
| 					}, | ||||
| 					{ | ||||
| 						label: '选项2', | ||||
| 						value: '' | ||||
| 					} | ||||
| 				], | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'select', | ||||
| 				fieldName: '单下拉框', | ||||
| 				fixedLabel: '单下拉框', | ||||
| 				grid: 0.5, | ||||
| 				fieldTips: '请选择', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				defaultValue: '', | ||||
| 				disable: '0', | ||||
| 				options: [ | ||||
| 					{ | ||||
| 						label: '选项1', | ||||
| 						value: '' | ||||
| 					}, | ||||
| 					{ | ||||
| 						label: '选项2', | ||||
| 						value: '' | ||||
| 					} | ||||
| 				], | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'onOff', | ||||
| 				fieldName: '开关', | ||||
| 				fixedLabel: '开关', | ||||
| 				grid: 0.5, | ||||
| 				fieldTips: '请选择开关', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				defaultValue: '0', | ||||
| 				disable: '0', | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'date', | ||||
| 				fieldName: '日期', | ||||
| 				fixedLabel: '日期', | ||||
| 				grid: 0.5, | ||||
| 				datetimePattern: 'yyyy-MM-dd', | ||||
| 				fieldTips: '请选择日期', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				disable: '0', | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'time', | ||||
| 				fieldName: '时间', | ||||
| 				fixedLabel: '时间', | ||||
| 				grid: 0.5, | ||||
| 				datetimePattern: 'HH:mm:ss', | ||||
| 				fieldTips: '请选择时间', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				disable: '0', | ||||
| 				title: '' | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'datetime', | ||||
| 				fieldName: '日期时间', | ||||
| 				fixedLabel: '日期时间', | ||||
| 				grid: 0.5, | ||||
| 				datetimePattern: 'yyyy-MM-dd HH:mm:ss', | ||||
| 				fieldTips: '请选择日期时间', | ||||
| 				icon: 'iconSelect', | ||||
| 				mustFill: '1', | ||||
| 				disable: '0', | ||||
| 				title: '' | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	{ | ||||
| 		type: 'input', | ||||
| 		tips: '(可重复添加)', | ||||
| 		label: '填空', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'input', | ||||
| 				fieldName: '单行填空', | ||||
| 				fieldTips: '请输入', | ||||
| 				fixedLabel: '单行填空', | ||||
| 				disable: '0', | ||||
| 				grid: 0.5, | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_box', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 50 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'textarea', | ||||
| 				fieldName: '多行填空', | ||||
| 				fixedLabel: '多行填空', | ||||
| 				fieldTips: '请输入', | ||||
| 				lineNumber: 4, | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 500, | ||||
| 				disable: '0', | ||||
| 				grid: 1 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'number', | ||||
| 				fieldName: '数字输入', | ||||
| 				fixedLabel: '数字输入', | ||||
| 				fieldTips: '请输入数字', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxValue: 10000, | ||||
| 				decimalPlaces: 0, | ||||
| 				minValue: 0, | ||||
| 				maxLength: 500, | ||||
| 				disable: '0', | ||||
| 				grid: 0.5 | ||||
| 			}, | ||||
| 			{ | ||||
| 				type: 'rtf', | ||||
| 				fieldName: '富文本', | ||||
| 				fixedLabel: '富文本', | ||||
| 				fieldTips: '请输入', | ||||
| 				defaultValue: '', | ||||
| 				icon: 'icontext_area', | ||||
| 				mustFill: '1', | ||||
| 				maxLength: 5000, | ||||
| 				disable: '0', | ||||
| 				grid: 1 | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	{ | ||||
| 		type: 'annex', | ||||
| 		tips: '(可重复添加)', | ||||
| 		label: '附件', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'upload', | ||||
| 				fieldTips: '请上传', | ||||
| 				fieldName: '上传附件', | ||||
| 				fixedLabel: '上传附件', | ||||
| 				disable: '0', | ||||
| 				fileChoseSize: 10, | ||||
| 				fileMaxCount: 9, | ||||
| 				defaultValue: '', | ||||
| 				icon: 'iconpic', | ||||
| 				mustFill: '1', | ||||
| 				grid: 1 | ||||
| 			} | ||||
| 		] | ||||
| 	}, | ||||
| 	{ | ||||
| 		type: 'layout', | ||||
| 		tips: '(可重复添加)', | ||||
| 		label: '分组', | ||||
| 		children: [ | ||||
| 			{ | ||||
| 				type: 'group', | ||||
| 				fieldName: '卡片', | ||||
| 				fixedLabel: '卡片', | ||||
| 				icon: 'iconpic', | ||||
| 				groupName: '分组标题', | ||||
| 				column: [] | ||||
| 			} | ||||
| 		] | ||||
| 	} | ||||
| ]; | ||||
							
								
								
									
										62
									
								
								project/sanjianxi/apps/AppIntegralAudit/AppIntegralAudit.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								project/sanjianxi/apps/AppIntegralAudit/AppIntegralAudit.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| <template> | ||||
|   <div class="AppHealthReport"> | ||||
|     <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.vue' | ||||
|   import Detail from './components/Detail.vue' | ||||
|  | ||||
|   export default { | ||||
|     name: 'AppIntegralAudit', | ||||
|     label: '积分审核(三涧溪)', | ||||
|  | ||||
|     components: { | ||||
|       List, | ||||
|       Detail | ||||
|     }, | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         component: 'List', | ||||
|         params: {} | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onChange (data) { | ||||
|         if (data.type === 'Detail') { | ||||
|           this.component = 'Detail' | ||||
|           this.isShowDetail = true | ||||
|           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" scoped> | ||||
|   .AppHealthReport { | ||||
|     height: 100%; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										269
									
								
								project/sanjianxi/apps/AppIntegralAudit/components/Detail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								project/sanjianxi/apps/AppIntegralAudit/components/Detail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,269 @@ | ||||
| <template> | ||||
|   <ai-detail class="audit"> | ||||
|     <template slot="title"> | ||||
|       <ai-title title="详情" isShowBack isShowBottomBorder @onBackClick="cancel(true)"> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-card title="基本信息"> | ||||
|         <template #content> | ||||
|           <ai-wrapper | ||||
|               label-width="120px"> | ||||
|             <ai-info-item label="申请人" :value="info.residentName"></ai-info-item> | ||||
|             <ai-info-item label="申请时间" :value="info.createTime"></ai-info-item> | ||||
|             <ai-info-item label="积分类型" :value="dict.getLabel('atWillReportType', info.applyIntegralType)"></ai-info-item> | ||||
|             <ai-info-item label="规则类型" :value="info.residentName"></ai-info-item> | ||||
|             <ai-info-item label="申请描述" :value="info.description" isLine></ai-info-item> | ||||
|             <!-- <ai-info-item label="联系电话" isLine :value="info.residentPhone"></ai-info-item> --> | ||||
|             <ai-info-item label="图片资料" isLine v-show="info.applyFiles"> | ||||
|               <ai-uploader v-model="info.applyFiles" disabled></ai-uploader> | ||||
|             </ai-info-item> | ||||
|           </ai-wrapper> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       <ai-card title="审核详情" v-if="info.auditStatus !== '0'"> | ||||
|         <div slot="content" style="margin-top: 16px;margin-bottom:24px"> | ||||
|           <ai-wrapper | ||||
|               label-width="120px"> | ||||
|             <ai-info-item label="审核结果" :value="info.auditStatus === '1' ? '通过' : '拒绝'"></ai-info-item> | ||||
|             <ai-info-item label="积分调整" isLine v-if="info.auditStatus === '1'" | ||||
|                           :value="(info.auditIntegral >= 0 ? info.auditIntegral : info.auditIntegral) + '分'"></ai-info-item> | ||||
|             <ai-info-item label="审核人" :value="info.auditUserName"></ai-info-item> | ||||
|             <ai-info-item label="审核时间" :value="info.auditTime"></ai-info-item> | ||||
|             <ai-info-item label="审核意见" v-if="info.auditStatus === '2'" isLine :value="info.auditOpinion"></ai-info-item> | ||||
|             <!-- <ai-info-item label="积分规则类别" v-if="info.auditStatus === '1'" :value="dict.getLabel('atWillReportType', info.auditIntegralType)"></ai-info-item> --> | ||||
|             <!-- <ai-info-item label="积分规则事项" v-if="info.auditStatus === '1'" :value="info.auditRuleName"></ai-info-item> --> | ||||
|           </ai-wrapper> | ||||
|         </div> | ||||
|       </ai-card> | ||||
|       <ai-dialog | ||||
|           :visible.sync="isShow" | ||||
|           width="800px" | ||||
|           @close="onClose" | ||||
|           title="事件审核" | ||||
|           @onConfirm="onConfirm"> | ||||
|         <el-form class="ai-form" label-width="120px" :model="form" ref="form"> | ||||
|  | ||||
|           <el-form-item label="是否通过审核" prop="pass" style="width: 100%;" :rules="[{ required: true, message: '请选择是否通过审核' }]"> | ||||
|             <el-radio-group v-model="form.pass" @change="onStatusChange"> | ||||
|               <el-radio label="0">否</el-radio> | ||||
|               <el-radio label="1">是</el-radio> | ||||
|             </el-radio-group> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="积分分值" prop="pass" style="width: 100%;" :rules="[{ required: true, message: '请输入积分分值' }]"> | ||||
|             <el-input v-model="num" placeholder="请输入1-10的整数"></el-input> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="积分分值" prop="pass" style="width: 100%;" :rules="[{ required: true, message: '请输入积分分值' }]"> | ||||
|             <el-input v-model="num" placeholder="请输入1-10的整数"></el-input> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="加分项" prop="pass" style="width: 100%;" :rules="[{ required: true, message: '请选择加分项' }]"> | ||||
|             <!-- <ai-select v-model="form.integralCalcType" :selectList="dict.getDict('integralCalcType')"/> --> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="积分分值" prop="pass" style="width: 100%;" :rules="[{ required: true, message: '请输入积分分值' }]"> | ||||
|             <el-input v-model="num" placeholder="请输入1-10的整数"></el-input> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <!-- <el-form-item v-if="form.pass === '1'" label="积分调整" prop="auditIntegral" style="width: 100%;" :rules="[{ required: true, message: '请输入积分调整' }]"> | ||||
|             <el-input v-model.number="form.auditIntegral" clearable placeholder="请输入积分调整" @keyup.native="form.auditIntegral=Math.abs(form.auditIntegral)"/> | ||||
|           </el-form-item> --> | ||||
|  | ||||
|           <!-- <el-form-item v-if="form.pass === '1'" label="积分规则类别" prop="auditRuleId" style="width: 100%;" :rules="[{ required: true, message: '' }]"> | ||||
|             <div class="flex-warpper"> | ||||
|               <el-form-item  label-width="0" prop="auditIntegralType" :rules="[{ required: true, message: '请选择积分规则类别' }]"> | ||||
|                 <ai-select | ||||
|                   v-model="form.auditIntegralType" clearable | ||||
|                   style="width: 180px;" | ||||
|                   placeholder="请选择积分规则类别" | ||||
|                   :selectList="dict.getDict('atWillReportType')" | ||||
|                   @change="onChange"> | ||||
|                 </ai-select> | ||||
|               </el-form-item> | ||||
|               <el-form-item style="margin: 0 10px;" prop="auditRuleId" :rules="[{ required: true, message: '请选择积分规则事项' }]"> | ||||
|                 <ai-select | ||||
|                   v-model="form.auditRuleId" | ||||
|                   clearable | ||||
|                   style="width: 180px;" | ||||
|                   placeholder="请选择积分规则事项" | ||||
|                   :selectList="ruleList"> | ||||
|                 </ai-select> | ||||
|               </el-form-item> | ||||
|               <span>{{ integralText }}</span> | ||||
|             </div> | ||||
|           </el-form-item> --> | ||||
|  | ||||
|           <el-form-item label="审核意见" v-if="form.pass === '0'" prop="opinion" style="width: 100%;" :rules="[{ required: true, message: '请输入审核意见' }]"> | ||||
|             <el-input type="textarea" :rows="5" :maxlength="200" v-model="form.opinion" clearable placeholder="请输入审核意见" show-word-limit></el-input> | ||||
|           </el-form-item> | ||||
|  | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|  | ||||
|     <template #footer v-if="info.auditStatus === '0'"> | ||||
|       <el-button @click="cancel">取消</el-button> | ||||
|       <el-button type="primary" @click="isShow = true">审核</el-button> | ||||
|     </template> | ||||
|  | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: 'Detail', | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     params: Object | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     const validatorRules = function (rule, value, callback) { | ||||
|       if (value === '') { | ||||
|         callback(new Error('请输入联系方式')) | ||||
|       } else if (!/^1\d{10}$/.test(value)) { | ||||
|         callback(new Error('手机号格式错误')) | ||||
|       } else { | ||||
|         callback() | ||||
|       } | ||||
|     } | ||||
|     return { | ||||
|       total: 0, | ||||
|       info: { | ||||
|         auditStatus: '0' | ||||
|       }, | ||||
|       id: '', | ||||
|       isShow: true, | ||||
|       form: { | ||||
|         auditIntegralType: '', | ||||
|         auditRuleId: '', | ||||
|         opinion: '', | ||||
|         pass: '' | ||||
|       }, | ||||
|       ruleList: [], | ||||
|       num: '' | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     integralText() { | ||||
|       if (!this.form.auditRuleId) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       const integral = this.ruleList.filter(v => v.dictValue === this.form.auditRuleId)[0].integral | ||||
|  | ||||
|       return integral >= 0 ? `+${integral}分` : `${integral}分` | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     let loading = this.$loading({ | ||||
|       text: 'Loading', | ||||
|     }); | ||||
|     if (this.params && this.params.id) { | ||||
|       this.id = this.params.id | ||||
|       this.dict.load(['atWillReportType', 'auditStatus']).then(() => { | ||||
|         this.getInfo(this.params.id) | ||||
|         this.$nextTick(() => { | ||||
|           loading.close() | ||||
|         }) | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getInfo(id) { | ||||
|       this.instance.post(`/app/appvillagerintegraldeclare/queryDetailById?id=${id}`).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           this.info = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onStatusChange() { | ||||
|       this.$refs.form.clearValidate() | ||||
|     }, | ||||
|  | ||||
|     onClose() { | ||||
|       this.form.auditIntegralType = '' | ||||
|       this.form.auditRuleId = '' | ||||
|       this.form.pass = '' | ||||
|       this.form.opinion = '' | ||||
|       this.id = '' | ||||
|     }, | ||||
|  | ||||
|     onConfirm() { | ||||
|       this.$refs.form.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post('/app/appvillagerintegraldeclare/examine', null, { | ||||
|             params: { | ||||
|               ...this.form, | ||||
|               id: this.params.id, | ||||
|             } | ||||
|           }).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.isShow = false | ||||
|               this.getInfo(this.params.id) | ||||
|               this.$message.success('审核成功!') | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onChange(e) { | ||||
|       this.form.auditRuleId = '' | ||||
|       this.instance.post(`/app/appvillagerintegralrule/list?size=1000&classification=${e}`).then(res => { | ||||
|         if (res?.code == 0) { | ||||
|           this.ruleList = res.data.records.filter(v => v.ruleStatus === '1').map(v => { | ||||
|             return { | ||||
|               dictName: v.ruleName, | ||||
|               dictValue: v.id, | ||||
|               ruleName: v.ruleName, | ||||
|               integral: v.integral | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     cancel(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: !!isRefresh | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .audit { | ||||
|   .flex-warpper { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|  | ||||
|     ::v-deep .el-form-item .el-form-item__content { | ||||
|       margin-left: 0 !important; | ||||
|     } | ||||
|  | ||||
|     ::v-deep .ai-select { | ||||
|       margin: 0 !important; | ||||
|     } | ||||
|  | ||||
|     ::v-deep .el-form-item { | ||||
|       width: auto; | ||||
|       margin-bottom: 0; | ||||
|  | ||||
|       &:last-child { | ||||
|         margin-right: 10px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										236
									
								
								project/sanjianxi/apps/AppIntegralAudit/components/List.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								project/sanjianxi/apps/AppIntegralAudit/components/List.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,236 @@ | ||||
| <template> | ||||
|   <ai-list class="list"> | ||||
|     <ai-title | ||||
|       slot="title" | ||||
|       title="积分审核" | ||||
|       v-if="search.areaId" | ||||
|       isShowBottomBorder | ||||
|       :instance="instance" | ||||
|       :disabledLevel="disabledLevel" | ||||
|       isShowArea | ||||
|       v-model="search.areaId" | ||||
|       @change="changeArea"> | ||||
|     </ai-title> | ||||
|     <template slot="content"> | ||||
|       <div class="content"> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <!-- <ai-select | ||||
|               v-model="search.applyIntegralType" | ||||
|               clearable | ||||
|               placeholder="请选择积分类型" | ||||
|               :selectList="dict.getDict('atWillReportType')" | ||||
|               @change="search.current = 1, getList()"> | ||||
|             </ai-select> --> | ||||
|             <ai-select | ||||
|               v-model="search.auditStatus" | ||||
|               clearable | ||||
|               placeholder="请选择审核状态" | ||||
|               :selectList="dict.getDict('auditStatus')" | ||||
|               @change="search.current = 1, getList()"> | ||||
|             </ai-select> | ||||
|             <el-date-picker | ||||
|               value-format="yyyy-MM-dd" | ||||
|               v-model="search.createTimeStart" | ||||
|               type="date" | ||||
|               size="small" | ||||
|               unlink-panels | ||||
|               placeholder="选择开始日期" | ||||
|               @change="search.current = 1, getList()" /> | ||||
|             <el-date-picker | ||||
|               value-format="yyyy-MM-dd" | ||||
|               v-model="search.createTimeEnd" | ||||
|               type="date" | ||||
|               size="small" | ||||
|               unlink-panels | ||||
|               placeholder="选择结束日期" | ||||
|               @change="search.current = 1, getList()" /> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input | ||||
|               v-model="search.residentName" | ||||
|               size="small" | ||||
|               placeholder="请输入姓名/事件类型" | ||||
|               clearable | ||||
|               v-throttle="() => {search.current = 1, getList()}" | ||||
|               @clear="search.current = 1, search.residentName = '', 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: 8px;" | ||||
|           :current.sync="search.current" | ||||
|           :size.sync="search.size" | ||||
|           @getList="getList"> | ||||
|           <el-table-column slot="options" width="120px" fixed="right" label="操作" align="center"> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <div class="table-options"> | ||||
|                 <el-button type="text" @click="toDetail(row.id)">详情</el-button> | ||||
|               </div> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </div> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import { mapState } from 'vuex' | ||||
|   export default { | ||||
|     name: 'List', | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         search: { | ||||
|           current: 1, | ||||
|           size: 10, | ||||
|           residentName: '', | ||||
|           applyIntegralType: '', | ||||
|           areaId: '', | ||||
|           auditStatus: '', | ||||
|           createTimeStart: '', | ||||
|           createTimeEnd: '' | ||||
|         }, | ||||
|         dictList: [{ | ||||
|           dictName: '否', | ||||
|           dictValue: '0' | ||||
|         }, { | ||||
|           dictName: '是', | ||||
|           dictValue: '1' | ||||
|         }], | ||||
|         info: {}, | ||||
|         colConfigs: [ | ||||
|           { prop: 'residentName', label: '申请人' }, | ||||
|           { prop: 'residentPhone', align: 'center', label: '联系电话' }, | ||||
|           { prop: 'createTime', align: 'center', label: '申请时间' }, | ||||
|           { prop: 'applyIntegralType', align: 'center', label: '积分类型', formart: v => this.dict.getLabel('atWillReportType', v) },  | ||||
|           { prop: 'auditStatus', align: 'center', label: '状态', formart: v => v ? this.dict.getLabel('auditStatus', v) : '-' },  | ||||
|           { prop: 'auditUserName', align: 'center', label: '审批人' },  | ||||
|           { prop: 'auditTime', align: 'center', label: '审批时间' } | ||||
|         ], | ||||
|         tableData: [], | ||||
|         total: 0, | ||||
|         loading: false, | ||||
|         disabledLevel: 0 | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       ...mapState(['user']), | ||||
|  | ||||
|       param () { | ||||
|         return { | ||||
|  | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.disabledLevel = this.user.info.areaList.length - 1 | ||||
|       this.search.areaId = this.user.info.areaId | ||||
|       this.loading = true | ||||
|       this.dict.load(['atWillReportType', 'auditStatus']).then(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.instance.post(`/app/appvillagerintegraldeclare/list`, null, { | ||||
|           params: { | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|             this.loading = false | ||||
|           } else { | ||||
|             this.loading = false | ||||
|           } | ||||
|         }).catch(() => { | ||||
|           this.loading = false | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       toDetail (id) { | ||||
|         this.$emit('change', { | ||||
|           type: 'Detail', | ||||
|           params: { | ||||
|             id: id || '' | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       changeArea () { | ||||
|         this.search.current = 1 | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           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 16px 12px!important; | ||||
|       } | ||||
|     } | ||||
|     .statistics-top { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       margin-bottom: 20px; | ||||
|  | ||||
|       & > div { | ||||
|         flex: 1; | ||||
|         height: 96px; | ||||
|         line-height: 1; | ||||
|         margin-right: 20px; | ||||
|         padding: 16px 24px; | ||||
|         background: #FFFFFF; | ||||
|         box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.15); | ||||
|         border-radius: 4px; | ||||
|  | ||||
|         &:last-child { | ||||
|           margin-right: 0; | ||||
|         } | ||||
|  | ||||
|         h3 { | ||||
|           font-size: 24px; | ||||
|         } | ||||
|  | ||||
|         span { | ||||
|           display: block; | ||||
|           margin-bottom: 16px; | ||||
|           color: #888888; | ||||
|           font-size: 16px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .content { | ||||
|       padding: 16px; | ||||
|       background: #FFFFFF; | ||||
|       box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.15); | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										35
									
								
								project/sanjianxi/apps/AppPartyScore/AppPartyScore.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								project/sanjianxi/apps/AppPartyScore/AppPartyScore.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <template> | ||||
|   <section class="AppPartyScore"> | ||||
|     <component :is="currentPage" v-bind="$props"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import PsList from "./psList"; | ||||
| import PsDetail from "./psDetail"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppPartyScore", | ||||
|   components: {PsDetail, PsList}, | ||||
|   label: "党员积分(三涧溪)", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     currentPage() { | ||||
|       return this.$route.query.id ? PsDetail : PsList | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load("partyIntegralType") | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppPartyScore { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										162
									
								
								project/sanjianxi/apps/AppPartyScore/psDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								project/sanjianxi/apps/AppPartyScore/psDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| <template> | ||||
|   <section class="psDetail"> | ||||
|     <ai-detail> | ||||
|       <ai-title slot="title" title="积分详情" isShowBottomBorder isShowBack @onBackClick="back"/> | ||||
|       <template #content> | ||||
|         <el-row type="flex"> | ||||
|           <ai-card hideTitle class="staCard fill"> | ||||
|             <template #content> | ||||
|               <div class="color-999" v-text="`姓名`"/> | ||||
|               <b v-text="detail.name"/> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card hideTitle class="staCard fill"> | ||||
|             <template slot="content"> | ||||
|               <div class="color-999" v-text="`党员积分`"/> | ||||
|               <b class="color-26f" v-text="detail.integral||0"/> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <!-- <ai-card hideTitle class="staCard fill"> | ||||
|             <template #content> | ||||
|               <div class="color-999" v-text="`学习强国`"/> | ||||
|               <el-button type="text" @click="handleEditLearningIntergral(detail.id)">编辑</el-button> | ||||
|               <b class="color-26f" v-text="detail.learningIntegral||0"/> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card hideTitle class="staCard fill"> | ||||
|             <template slot="content"> | ||||
|               <div class="color-999" v-text="`个人积分`"/> | ||||
|               <b class="color-26f" v-text="detail.integral||0"/> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-card hideTitle class="staCard fill"> | ||||
|             <template #content> | ||||
|               <div class="color-999" v-text="`家庭积分`"/> | ||||
|               <b class="color-26f" v-text="detail.familySurplusIntegral||0"/> | ||||
|             </template> | ||||
|           </ai-card> --> | ||||
|         </el-row> | ||||
|         <ai-card title="余额变动明细"> | ||||
|           <template #content> | ||||
|             <ai-table :tableData="detail.integralInfoList" :isShowPagination="false" :col-configs="colConfigs" | ||||
|                       :dict="dict"/> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </template> | ||||
|     </ai-detail> | ||||
|     <ai-dialog :visible.sync="dialog" title="学习强国设置" width="500px" @close="form={}" @onConfirm="submit"> | ||||
|       <el-form :model="form" size="small" ref="DialogForm" :rules="rules" label-width="110px"> | ||||
|         <el-form-item label="学习强国积分" prop="learningIntegral"> | ||||
|           <el-input v-model.number="form.learningIntegral" placeholder="请输入正整数" clearable/> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "psDetail", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       detail: {}, | ||||
|       colConfigs: [ | ||||
|         {label: "时间", prop: "createTime"}, | ||||
|         {label: "类型", prop: "integralType", align: 'center', dict: "partyIntegralType"}, | ||||
|         {label: "变动积分", prop: "integral", align: 'center'}, | ||||
|         {label: "剩余积分", prop: "residualIntegral", align: 'center'}, | ||||
|         {label: "调整说明", prop: "remark"}, | ||||
|       ], | ||||
|       dialog: false, | ||||
|       form: {}, | ||||
|       rules: { | ||||
|         learningIntegral: [ | ||||
|           {required: true, message: "请输入学习强国积分"}, | ||||
|           {pattern: /^\d+$/g, message: "请输入正整数"} | ||||
|         ] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getDetail() { | ||||
|       let {id} = this.$route.query | ||||
|       this.instance.post("/app/appparty/getPartyIntegralDetail", null, { | ||||
|         params: {id} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.detail = res.data | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     back() { | ||||
|       this.$router.push({}) | ||||
|     }, | ||||
|     submit() { | ||||
|       this.$refs.DialogForm.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post("/app/appparty/editLearningIntegral", null,{ | ||||
|             params:this.form | ||||
|           }).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success("提交成功!") | ||||
|               this.dialog = false | ||||
|               this.getDetail() | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleEditLearningIntergral(partyMemberId) { | ||||
|       this.dialog = true | ||||
|       this.form = {partyMemberId} | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getDetail() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .psDetail { | ||||
|   height: 100%; | ||||
|  | ||||
|   .color-999 { | ||||
|     color: #999; | ||||
|   } | ||||
|  | ||||
|   .color-26f { | ||||
|     color: #26f; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .staCard { | ||||
|     font-size: 14px; | ||||
|     width: 25%; | ||||
|  | ||||
|     b { | ||||
|       font-size: 24px; | ||||
|       line-height: 40px; | ||||
|     } | ||||
|  | ||||
|     & + .staCard { | ||||
|       margin-left: 16px; | ||||
|       width: 25%; | ||||
|     } | ||||
|  | ||||
|     .ai-card__body { | ||||
|       position: relative; | ||||
|  | ||||
|       .el-button { | ||||
|         position: absolute; | ||||
|         right: 32px; | ||||
|         top: 6px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										175
									
								
								project/sanjianxi/apps/AppPartyScore/psList.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								project/sanjianxi/apps/AppPartyScore/psList.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| <template> | ||||
|   <section class="psList"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="党员积分" isShowBottomBorder/> | ||||
|       <template #left> | ||||
|  | ||||
|         <ai-tree-menu title="组织目录" searchPlaceholder="请输入党组织名称" @search="onSearch"> | ||||
|           <ai-party-tree | ||||
|               :filter-node-method="filterNode" | ||||
|               ref="tree" | ||||
|               :instance="instance" | ||||
|               :root="user.info.organizationId" | ||||
|               :current-node-key="user.info.id" | ||||
|               @select="onTreeChange"/> | ||||
|         </ai-tree-menu> | ||||
|       </template> | ||||
|       <template #content> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <div>统计周期</div> | ||||
|             <el-date-picker type="daterange" placeholder="日期" size="small" clearable v-model="createTime" | ||||
|                         @change="handleSearchTime" start-placeholder="开始时间" end-placeholder="结束时间" | ||||
|                         value-format="yyyy-MM-dd HH:mm:ss" :default-time="['00:00:00','23:59:59']"/> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input size="small" placeholder="党员姓名" v-model="search.partyName" clearable | ||||
|                       @change="page.current=1,getTableData()" suffix-icon="iconfont iconSearch"/> | ||||
|             <ai-download :instance="instance" url="/app/apppartyintegralinfo/downloadTemplate" :params="search" fileName="党员积分" :disabled="tableData.length == 0"> | ||||
|               <el-button icon="iconfont iconExported" :disabled="tableData.length == 0">导出</el-button> | ||||
|             </ai-download> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :total="page.total" :current.sync="page.current" :size.sync="page.size" | ||||
|                   @getList="getTableData" :col-configs="colConfigs" :dict="dict"> | ||||
|           <el-table-column slot="options" label="操作" fixed="right" align="center"> | ||||
|             <template slot-scope="{row}"> | ||||
|               <el-button type="text" @click="getFamilyByPartyId(row.idNumber)">家庭成员</el-button> | ||||
|               <el-button type="text" @click="showDetail(row.id)">详情</el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <ai-dialog :visible.sync="dialog" title="家庭成员" :customFooter="true" width="780px" @close="familyList=[]"> | ||||
|       <ai-table :tableData="familyList" :isShowPagination="false" :col-configs="familyCols" :dict="dict"/> | ||||
|       <div class="dialog-footer" slot="footer"> | ||||
|         <el-button @click="dialog=false">关 闭</el-button> | ||||
|       </div> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { mapState } from "vuex"; | ||||
|  | ||||
| export default { | ||||
|   name: "psList", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {label: "排行榜", prop: "name", align: "center"}, | ||||
|         {label: "党员姓名", prop: "name", align: "center"}, | ||||
|         {label: "党员类型", prop: "name", align: "center"}, | ||||
|         {label: "获得积分", prop: "name", align: "center"}, | ||||
|         // {label: "个人积分", prop: "integral", align: "center"}, | ||||
|         // {label: "家庭积分", prop: "familySurplusIntegral", align: "center"}, | ||||
|         // {label: "学习强国", prop: "learningIntegral", align: "center"}, | ||||
|         {slot: "options"} | ||||
|       ] | ||||
|     }, | ||||
|     familyCols() { | ||||
|       return [ | ||||
|         { | ||||
|           label: '与户主关系', prop: 'householdRelation', align: 'center', width: 165, | ||||
|           render: (h, {row}) => h('p', this.dict.getLabel('householdRelation', row.householdRelation || "户主")) | ||||
|         }, | ||||
|         {label: '类型', prop: 'residentType', align: 'center', dict: "residentType"}, | ||||
|         {label: '姓名', prop: 'name', align: 'center'}, | ||||
|         {label: '身份证号', render: (h, {row}) => h('p', this.idCardNoUtil.hideId(row.idNumber)), width: 165}, | ||||
|         {label: '联系电话', prop: 'phone', align: 'center', width: 120} | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       search: { | ||||
|         createTime: '', | ||||
|       }, | ||||
|       page: {current: 1, size: 10, total: 0}, | ||||
|       tableData: [], | ||||
|       dialog: false, | ||||
|       familyList: [], | ||||
|       organizationName: '', | ||||
|       organizationTree: [], | ||||
|       defaultExpanded: [], | ||||
|       defaultChecked: [], | ||||
|       areaTree: [], | ||||
|       defaultProps: { | ||||
|         children: 'children', | ||||
|         label: 'name' | ||||
|       }, | ||||
|       createTime: '', | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     back() { | ||||
|       this.$router.push({}) | ||||
|     }, | ||||
|     getTableData() { | ||||
|       this.instance.post("/app/appparty/listByPartyIntegral", null, { | ||||
|         params: {...this.page, ...this.search} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data?.records | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|      | ||||
|     onSearch(v) { | ||||
|       this.orgTree.filter(v) | ||||
|     }, | ||||
|  | ||||
|     onTreeChange(e) { | ||||
|       this.search.areaId = e.id | ||||
|       this.areaName = e.name | ||||
|       this.search.current = 1 | ||||
|  | ||||
|       this.$nextTick(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     filterNode(value, data) { | ||||
|       if (!value) return true | ||||
|       return data.name.indexOf(value) !== -1 | ||||
|     }, | ||||
|  | ||||
|     handleSearchTime(v) { | ||||
|       // this.page.current = 1 | ||||
|       // this.search.startTime = v?.[0] | ||||
|       // this.search.endTime = v?.[1] | ||||
|       // this.getTableData() | ||||
|     }, | ||||
|  | ||||
|     showDetail(id) { | ||||
|       this.$router.push({query: {id}}) | ||||
|     }, | ||||
|     getFamilyByPartyId(idNumber) { | ||||
|       this.instance.post("/app/appresident/queryHomeMember", null, { | ||||
|         params: {idNumber} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.familyList = res.data?.family || [] | ||||
|           this.dialog = true | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTableData() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .psList { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
| @@ -0,0 +1,34 @@ | ||||
| <template> | ||||
|   <section class="AppPartyScoreFlow"> | ||||
|     <component :is="currentPage" v-bind="$props"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import PsfList from "./psfList"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppPartyScoreFlow", | ||||
|   components: {PsfList}, | ||||
|   label: "积分明细(三涧溪)", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     currentPage() { | ||||
|       return PsfList | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load("partyIntegralType") | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppPartyScoreFlow { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										156
									
								
								project/sanjianxi/apps/AppPartyScoreFlow/psfList.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								project/sanjianxi/apps/AppPartyScoreFlow/psfList.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | ||||
| <template> | ||||
|   <section class="psfList"> | ||||
|     <ai-list> | ||||
|       <ai-title slot="title" title="党员积分明细" isShowBottomBorder/> | ||||
|       <template #content> | ||||
|         <ai-search-bar> | ||||
|           <template #left> | ||||
|             <el-button type="primary" icon="iconfont iconAdd" @click="dialog=true">添加</el-button> | ||||
|             <el-date-picker type="daterange" placeholder="日期" size="small" clearable v-model="createTime" | ||||
|                             @change="handleSearchTime" start-placeholder="开始时间" end-placeholder="结束时间" | ||||
|                             value-format="yyyy-MM-dd HH:mm:ss" :default-time="['00:00:00','23:59:59']"/> | ||||
|           </template> | ||||
|           <template #right> | ||||
|             <el-input size="small" placeholder="搜索党员" v-model="search.partyName" clearable | ||||
|                       @change="page.current=1,getTableData()" suffix-icon="iconfont iconSearch"/> | ||||
|             <ai-import :instance="instance" :dict="dict" importUrl="/appcollectiveeconomyequity/import" url="/appcollectiveeconomyequity/downloadTemplate" name="集体经济组织股权管理信息" @success="getTableData(), $message.success('导入成功!')"> | ||||
|               <el-button size="small">导入</el-button> | ||||
|             </ai-import> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table :tableData="tableData" :total="page.total" :current.sync="page.current" :size.sync="page.size" | ||||
|                   @getList="getTableData" :col-configs="colConfigs" :dict="dict"> | ||||
|           <el-table-column slot="options" label="操作" fixed="right" align="center"> | ||||
|             <template slot-scope="{row}"> | ||||
|               <el-button type="text" @click="showDetail(row)">详情</el-button> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <ai-dialog :visible.sync="dialog" title="积分对象" width="600px" @close="form={}" @onConfirm="submit" | ||||
|                :customFooter="!isAdd"> | ||||
|       <el-form v-if="isAdd" :model="form" size="small" ref="DialogForm" :rules="rules" label-width="80px"> | ||||
|         <el-form-item label="选择人员" prop="partyId"> | ||||
|           <ai-select v-model="form.partyId" action="/app/appparty/list" :instance="instance" | ||||
|                      :prop="{label:'name'}"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="调整说明" prop="remark"> | ||||
|           <el-input type="textarea" placeholder="请输入" v-model="form.remark" maxlength="100" show-word-limit rows="3" | ||||
|                     clearable/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="类型" prop="integralType"> | ||||
|           <ai-select v-model="form.integralType" :selectList="dict.getDict('partyIntegralType')"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="积分" prop="integral"> | ||||
|           <el-input v-model.number="form.integral" placeholder="请输入正整数" clearable/> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <ai-wrapper v-else> | ||||
|         <ai-info-item label="对象" :value="form.partyName"/> | ||||
|         <ai-info-item label="调整说明" :value="form.remark" isLine/> | ||||
|         <ai-info-item label="类型" :value="dict.getLabel('partyIntegralType',form.integralType)"/> | ||||
|         <ai-info-item label="积分" :value="form.integral"/> | ||||
|       </ai-wrapper> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
|  | ||||
| export default { | ||||
|   name: "psfList", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {label: "对象", prop: "partyName"}, | ||||
|         {label: "调整说明", prop: "remark", align: "center"}, | ||||
|         {label: "时间", prop: "createTime"}, | ||||
|         {label: "类型", prop: "integralType", align: "center", dict: "partyIntegralType"}, | ||||
|         {label: "积分", prop: "integral", align: "center"}, | ||||
|         {slot: "options"} | ||||
|       ] | ||||
|     }, | ||||
|     isAdd() { | ||||
|       return !this.form.id | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       search: {}, | ||||
|       page: {current: 1, size: 10, total: 0}, | ||||
|       tableData: [], | ||||
|       dialog: false, | ||||
|       form: {}, | ||||
|       rules: { | ||||
|         partyId: {required: true, message: "请选择人员"}, | ||||
|         remark: {required: true, message: "请输入调整说明"}, | ||||
|         integralType: {required: true, message: "请选择类型"}, | ||||
|         integral: [ | ||||
|           {required: true, message: "请输入分数"}, | ||||
|           {pattern: /^\d+$/g, message: "请输入正整数"} | ||||
|         ], | ||||
|       }, | ||||
|       createTime: "", | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getTableData() { | ||||
|       this.instance.post("/app/apppartyintegralinfo/list", null, { | ||||
|         params: {...this.page, ...this.search} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data?.records?.map(e => ({ | ||||
|             ...e, | ||||
|             integral: (e.integralType == 0 ? "-" : '+') + e.integral | ||||
|           })) | ||||
|           this.page.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|      | ||||
|     showDetail(row) { | ||||
|       this.form = JSON.parse(JSON.stringify(row)) | ||||
|       this.dialog = true | ||||
|     }, | ||||
|     submit() { | ||||
|       this.$refs.DialogForm.validate(v => { | ||||
|         if (v) { | ||||
|           let loading = this.$loading({text: "提交中..."}) | ||||
|           this.instance.post("/app/apppartyintegralinfo/addOrUpdate", this.form).then(res => { | ||||
|             loading.close() | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success("提交成功!") | ||||
|               this.dialog = false | ||||
|               this.getTableData() | ||||
|             } | ||||
|           }).catch(() => loading.close()) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleSearchTime(v) { | ||||
|       this.page.current = 1 | ||||
|       this.search.startTime = v?.[0] | ||||
|       this.search.endTime = v?.[1] | ||||
|       this.getTableData() | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTableData() | ||||
|      | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .psfList { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										355
									
								
								project/sanjianxi/apps/AppScoreRules/AppScoreRules.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										355
									
								
								project/sanjianxi/apps/AppScoreRules/AppScoreRules.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,355 @@ | ||||
| <template> | ||||
|   <section class="AppScoreRules"> | ||||
|     <ai-list v-if="permissions('app_appvillagerintegralrule_detail')"> | ||||
|       <template slot="title"> | ||||
|         <ai-title title="积分规则" isShowBottomBorder></ai-title> | ||||
|       </template> | ||||
|       <template slot="content"> | ||||
|         <ai-search-bar bottomBorder> | ||||
|           <template slot="left"> | ||||
|             <!-- <el-cascader size="small" v-model="search.eventType" placeholder="请选择事件/类型" clearable | ||||
|                          :props="{...etOps,checkStrictly:true}" @change="handleTypeSearch" ref="eventTypeSearch"/> --> | ||||
|             <ai-select | ||||
|                 v-model="search.status" | ||||
|                 @change="page.current = 1, getList()" | ||||
|                 placeholder="请选择状态" | ||||
|                 :selectList="dict.getDict('integralRuleStatus')"> | ||||
|             </ai-select> | ||||
|           </template> | ||||
|           <template slot="right"> | ||||
|             <el-input size="small" placeholder="事件名称" v-model="search.partyName" clearable | ||||
|                       @change="page.current=1,getTableData()" suffix-icon="iconfont iconSearch"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|  | ||||
|         <ai-search-bar style="margin-top: 16px;"> | ||||
|           <template #left> | ||||
|             <el-button type="primary" icon="iconfont iconAdd" @click="dialog=true">添加</el-button> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|  | ||||
|         <ai-table | ||||
|             :tableData="tableData" | ||||
|             :col-configs="colConfigs" | ||||
|             :total="page.total" :dict="dict" | ||||
|             :current.sync="page.current" | ||||
|             :size.sync="page.size" | ||||
|             @getList="getList"> | ||||
|           <el-table-column slot="integral" label="分值" align="center"> | ||||
|             <template slot-scope="{ row }"> | ||||
|             <span | ||||
|                 v-if="row.integralValueType == 1"> | ||||
|               {{ row.integralStart > 0 ? '+' + row.integralStart : row.integralStart }} ~ {{ row.integralEnd > 0 ? '+' + row.integralEnd : row.integralEnd }} | ||||
|             </span> | ||||
|               <span v-else>{{ row.integral > 0 ? '+' : '' }}{{ row.integral }}</span> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|           <el-table-column slot="options" label="操作" align="center" fixed="right" width="200"> | ||||
|             <template slot-scope="{ row }"> | ||||
|               <div class="table-options"> | ||||
|                 <el-button type="text" :disabled="!permissions('app_appvillagerintegralrule_edit')" @click="changeStatus(row.id, 0)" v-if="row.status == 1"> | ||||
|                   停用 | ||||
|                 </el-button> | ||||
|                 <el-button type="text" :disabled="!permissions('app_appvillagerintegralrule_edit')" @click="changeStatus(row.id, 1)" v-else>启用</el-button> | ||||
|                 <el-button type="text" :disabled="!permissions('app_appvillagerintegralrule_edit')" @click="toEdit(row)">编辑</el-button> | ||||
|                 <el-button type="text" :disabled="!permissions('app_appvillagerintegralrule_del')" @click="remove(row.id)">删除</el-button> | ||||
|               </div> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|  | ||||
|       </template> | ||||
|     </ai-list> | ||||
|  | ||||
|     <ai-empty v-else>暂无应用权限</ai-empty> | ||||
|  | ||||
|     <ai-dialog :title="dialogTitle" :visible.sync="dialog" @onConfirm="onConfirm" @closed="form={ladderRule: []}" width="800px"> | ||||
|       <div class="form_div"> | ||||
|         <el-form ref="DialogForm" :model="form" :rules="formRules" size="small" label-suffix=":" label-width="100px"> | ||||
|           <!-- <el-form-item label="事件/类型" prop="eventType"> | ||||
|             <el-cascader v-model="form.eventType" :props="etOps" clearable placeholder="请选择" @change="handleTypeForm" | ||||
|                          :options="cacheOps"/> | ||||
|           </el-form-item> --> | ||||
|           <el-form-item label="事件名称" prop="eventType"> | ||||
|             <el-input v-model="form.name" clearable placeholder="请输入事件名称" type="text" maxlength="30" show-word-limit/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="简介说明" prop="eventType"> | ||||
|             <el-input v-model="form.name" clearable placeholder="请输入简介说明" type="text" maxlength="100" show-word-limit/> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="规则" prop="ruleType" required> | ||||
|             <el-radio-group v-model.trim="form.pass" @change="typeChange"> | ||||
|               <el-radio :label="0">常规</el-radio> | ||||
|               <el-radio :label="1">区间</el-radio> | ||||
|               <el-radio :label="2">阶梯</el-radio> | ||||
|             </el-radio-group> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="周期范围" prop="scoringCycle"> | ||||
|             <ai-select v-model="form.scoringCycle" :selectList="dict.getDict('integralRuleScoringCycle')"/> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="奖励次数"> | ||||
|             <el-input placeholder="请输入,周期范围内,不填写表示不限制" v-model.number="form.numberLimit" clearable/> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="积分分值" prop="integral" v-if="form.pass == 0"> | ||||
|             <el-input placeholder="请输入" v-model="form.integral" clearable/> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-form-item label="积分分值" prop="integral" v-if="form.pass == 1"> | ||||
|             <ai-range v-model="form.num" ref="resetagefoo" /> | ||||
|           </el-form-item> | ||||
|            | ||||
|           <el-form-item label="积分分值" prop="integral" v-if="form.pass == 2"> | ||||
|             <el-button type="text" @click="innerVisible  = true" style="float: right;">添加</el-button> | ||||
|             <ai-table :tableData="integralData" :isShowPagination="false" :col-configs="integralConfigs" :dict="dict"> | ||||
|               <el-table-column slot="options" align="center" label="操作" fixed="right" width="160px"> | ||||
|                 <el-row type="flex" justify="center" align="middle" slot-scope="{row}"> | ||||
|                   <el-button v-if="$permissions('admin_sysuser_distribute')&&!!row.sysUserId" | ||||
|                             type="text" @click="appAllot(row)">删除 | ||||
|                   </el-button> | ||||
|                 </el-row> | ||||
|               </el-table-column> | ||||
|             </ai-table> | ||||
|           </el-form-item> | ||||
|  | ||||
|           <el-dialog width="30%" title="添加积分分值" :visible.sync="innerVisible" append-to-body> | ||||
|             <el-form ref="innerForm" :model="table" :rules="formRules" size="small" label-suffix=":" label-width="100px"> | ||||
|               <el-form-item label="加分项" prop="integral"> | ||||
|                 <el-input placeholder="请输入" v-model="form.integral" clearable/> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="获得积分" prop="integral"> | ||||
|                 <el-input placeholder="请输入" v-model="form.integral" clearable/> | ||||
|               </el-form-item> | ||||
|             </el-form> | ||||
|  | ||||
|             <div slot="footer" class="dialog-footer"> | ||||
|               <el-button @click="innerVisible = false">取 消</el-button> | ||||
|               <el-button type="primary" @click="save">保存</el-button> | ||||
|             </div> | ||||
|           </el-dialog> | ||||
|         </el-form> | ||||
|       </div> | ||||
|  | ||||
|        | ||||
|  | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| export default { | ||||
|   name: "AppScoreRules", | ||||
|   label: "积分规则(三涧溪)", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     isEdit() { | ||||
|       return !!this.form.id | ||||
|     }, | ||||
|     dialogTitle() { | ||||
|       return this.isEdit ? "编辑积分规则" : "添加积分规则" | ||||
|     }, | ||||
|     etOps() { | ||||
|       return { | ||||
|         lazy: true, | ||||
|         value: "dictValue", | ||||
|         label: "dictName", | ||||
|         lazyLoad: (node, resolve) => { | ||||
|           if (node.level == 0) resolve(this.dict.getDict('integralRuleEvent')) | ||||
|           else if (node.level == 1) { | ||||
|             let dict = 'integralRuleEvent' + node.value | ||||
|             this.dict.load(dict).then(() => { | ||||
|               let nodes = this.dict.getDict(dict).map(e => ({...e, leaf: true})) | ||||
|               resolve(nodes) | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       search: {status: "", eventType: null}, | ||||
|       page: {current: 1, size: 10, total: 0}, | ||||
|       colConfigs: [ | ||||
|         {prop: "event", label: "事件", dict: "integralRuleEvent"}, | ||||
|         {prop: "type", label: "类型", dict: "integralRuleEventType"}, | ||||
|         {prop: "ruleType", label: "规则", dict: "integralRuleRuleType"}, | ||||
|         {prop: "scoringCycle", label: "周期范围", dict: "integralRuleScoringCycle"}, | ||||
|         {prop: "status", label: "状态", align: "center", width: 96, dict: "integralRuleStatus"}, | ||||
|         {slot: "options", label: "操作", align: "center"}, | ||||
|       ], | ||||
|       integralConfigs: [ | ||||
|         {prop: "event", label: "加分项", dict: "integralRuleEvent"}, | ||||
|         {prop: "event", label: "获得积分", dict: "integralRuleEvent"}, | ||||
|         {slot: "options", label: "操作", align: "center"}, | ||||
|       ], | ||||
|       tableData: [], | ||||
|       dialog: false, | ||||
|       form: { | ||||
|         ladderRule: [], | ||||
|         pass: '0', | ||||
|       }, | ||||
|       formRules: { | ||||
|         eventType: [{required: true, message: "请选择事件/类型", trigger: "change"}], | ||||
|         scoringCycle: [{required: true, message: "请选择周期范围", trigger: "change"}], | ||||
|         integral: [{required: true, pattern: /^\d*[.\d]\d?$/, message: "请输入积分分值,最多保留一位小数"}], | ||||
|         numberLimit: [{pattern: /^\d*$/, message: "请输入正整数"}] | ||||
|       }, | ||||
|       cacheOps: [], | ||||
|       integralFrom: '', | ||||
|       integralTo: '', | ||||
|       integralData: [], | ||||
|       innerVisible: false, | ||||
|       table: {}, | ||||
|        | ||||
|     }; | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load("integralRuleStatus", "integralRuleRuleType", 'integralRuleScoringCycle', 'integralRuleEvent', 'integralRuleEventType').then(() => { | ||||
|       this.getList(); | ||||
|     }); | ||||
|   }, | ||||
|   methods: { | ||||
|     getList() { | ||||
|       this.instance.post(`/app/appvillagerintegralrule/list`, null, { | ||||
|         params: {...this.search, ...this.page}, | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.tableData = res.data.records; | ||||
|           this.page.total = res.data.total; | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     toEdit(row) { | ||||
|       this.form = this.$copy(row) | ||||
|       let {ladderRule, event, type} = this.form, | ||||
|           dict = 'integralRuleEvent' + event | ||||
|       this.dict.load(dict).then(() => { | ||||
|         this.form.eventType = [event, type] | ||||
|         this.form.ladderRule = JSON.parse(ladderRule || "[]") | ||||
|         this.cacheOps = this.dict.getDict('integralRuleEvent').map(e => { | ||||
|           if (e.dictValue == event) { | ||||
|             e.children = this.dict.getDict(dict).map(d => ({...d, leaf: true})) | ||||
|           } | ||||
|           return e | ||||
|         }) | ||||
|         this.$nextTick(() => { | ||||
|           this.dialog = true | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|     // 保存 | ||||
|     save() { | ||||
|       this.$refs.innerForm.validate((valid)=>{ | ||||
|         if (valid) { | ||||
|           this.innerData.push(this.table) | ||||
|         } | ||||
|         this.innerVisible = false | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     typeChange(val) { | ||||
|       this.form.pass = val | ||||
|     }, | ||||
|  | ||||
|     handleInputFrom(event) { | ||||
|       this.$emit('focusfrom', event) | ||||
|     }, | ||||
|  | ||||
|     handleInputTo(event) { | ||||
|       this.$emit('blurto', event) | ||||
|     }, | ||||
|  | ||||
|     remove(id) { | ||||
|       this.$confirm("删除后不可恢复,是否要删除该事项?", { | ||||
|         type: 'error' | ||||
|       }).then(() => { | ||||
|         this.instance | ||||
|         .post(`/app/appvillagerintegralrule/delete?ids=${id}`) | ||||
|         .then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success("删除成功!"); | ||||
|             this.getList(); | ||||
|           } | ||||
|         }); | ||||
|       }); | ||||
|     }, | ||||
|     changeStatus(id, status) { | ||||
|       let text = status == 1 ? '启用' : '停用' | ||||
|       this.$confirm(`确定${text}该条规则?`).then(() => { | ||||
|         this.instance.post(`/app/appvillagerintegralrule/enableOrDisable?id=${id}`).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success(`${text}成功!`) | ||||
|             this.getList(); | ||||
|           } | ||||
|         }); | ||||
|       }); | ||||
|     }, | ||||
|     onReset() { | ||||
|       this.page.current = 1 | ||||
|       this.search.classification = "" | ||||
|       this.search.integralType = "" | ||||
|       this.search.ruleStatus = "" | ||||
|       this.getList(); | ||||
|     }, | ||||
|     onConfirm() { | ||||
|       if(this.form.ruleType==1 && !this.form.ladderRule.length) { | ||||
|         return this.$message.error('请添加规则') | ||||
|       } | ||||
|       this.$refs.DialogForm.validate((valid) => { | ||||
|         if (valid) { | ||||
|           let formData = this.$copy(this.form) | ||||
|           formData.ladderRule = JSON.stringify(formData.ladderRule) | ||||
|           formData.integral = formData.integral || 0 | ||||
|           this.instance.post(`/app/appvillagerintegralrule/addOrUpdate`, formData).then((res) => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success(`${this.isEdit ? '编辑成功' : '添加成功'}`) | ||||
|               this.onReset() | ||||
|               this.dialog = false; | ||||
|             } | ||||
|           }); | ||||
|         } else { | ||||
|           return false; | ||||
|         } | ||||
|       }); | ||||
|     }, | ||||
|     handleTypeSearch(v) { | ||||
|       this.search.event = v?.[0] | ||||
|       this.search.type = v?.[1] | ||||
|       this.page.current = 1 | ||||
|       this.$refs.eventTypeSearch.dropDownVisible = false | ||||
|       this.getList() | ||||
|     }, | ||||
|     handleTypeForm(v) { | ||||
|       if (this.dialog) { | ||||
|         this.form.event = v?.[0] | ||||
|         this.form.type = v?.[1] | ||||
|         this.form.ruleType = !this.form.event ? null : this.form.event == 3 ? 1 : 0 | ||||
|       } | ||||
|     }, | ||||
|     handleDelete(i) { | ||||
|       this.$confirm("是否要删除该规则?").then(() => { | ||||
|         this.form.ladderRule.splice(i, 1) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     checkIntegral(v) { | ||||
|       return /\.\d{2,}$/.test(v) ? Math.abs(v).toFixed(1) : Math.abs(v) | ||||
|     } | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppScoreRules { | ||||
|   height: 100%; | ||||
|   background: #f3f6f9; | ||||
|  | ||||
|    | ||||
|  | ||||
| } | ||||
| </style> | ||||
		Reference in New Issue
	
	Block a user