Merge branch 'dev' into vite

# Conflicts:
#	examples/main.js
#	examples/router/autoRoutes.js
#	package.json
#	packages/bigscreen/designer/AppDesigner.vue
#	packages/bigscreen/designer/components/Add.vue
#	packages/bigscreen/designer/components/Layout.vue
#	packages/bigscreen/designer/components/List.vue
#	packages/bigscreen/designer/components/SourceData.vue
#	packages/bigscreen/designer/components/form/DataConfig.vue
#	packages/bigscreen/designer/config.js
#	packages/bigscreen/viewer/AppGigscreenViewer.vue
#	packages/conv/creditScore/scoreManage/scoreChange.vue
#	packages/index.js
#	project/dv/apps/AppGridDV.vue
#	project/dvui/components/AiMonitor/dhVideo.vue
#	project/dvui/components/AiSwiper.vue
#	project/dvui/layout/AiDvBackground.vue
#	project/dvui/layout/AiDvSummary/AiDvSummary.vue
#	project/dvui/layout/AiDvWrapper/AiDvWrapper.vue
#	project/dvui/package.json
#	public/index.html
#	vue.config.js
This commit is contained in:
aixianling
2022-07-07 09:01:40 +08:00
208 changed files with 14871 additions and 8799 deletions

View File

@@ -2,3 +2,4 @@ apps/
index.js
*.map
vcapps.import.js
dist/

View File

@@ -1,7 +1,11 @@
<template>
<section class="AppAccount">
<ai-list>
<ai-title slot="title" title="账号管理" isShowBottomBorder/>
<ai-title slot="title" title="账号管理" isShowBottomBorder>
<template #rightBtn>
<el-button size="small" type="primary" icon="iconfont iconUpdate_Files" @click="syncDept">同步部门</el-button>
</template>
</ai-title>
<template #left>
<ai-address-book-menu :instance="instance" @select="handleSelect"/>
</template>
@@ -10,6 +14,7 @@
<ai-search-bar>
<template #left>
<el-button type="primary" :disabled="!ids.toString()" @click="batchAllot">功能分配</el-button>
<el-button size="small" icon="iconfont iconUpdate_Files" @click="syncMembers">同步成员</el-button>
</template>
<template #right>
<el-input size="small" placeholder="搜索姓名、手机号" v-model="search.name" clearable
@@ -72,7 +77,7 @@ import AiAddressBookMenu from "../../components/AiAddressBookMenu";
export default {
name: "AppAccount",
components: {AiAddressBookMenu},
label: "账号管理(村微sass版)",
label: "账号管理(村微版)",
props: {
instance: Function,
dict: Object,
@@ -223,6 +228,36 @@ export default {
}
})
},
syncMembers() {
const {departmentId = 1} = this.search;
let loading = this.$loading({
text: "正在同步成员...",
spinner: 'el-icon-loading',
background: "rgba(0,0,0,.8)"
})
this.instance.post(`/app/wxcp/wxdepartment/syncUser`, null, {
timeout: 1000000,
params: {departmentId}
}).then(res => {
if (res?.code == 0) {
this.$message.success('同步成功')
this.getList()
}
}).finally(() => loading.close())
},
syncDept() {
let loading = this.$loading({
text: "正在同步部门...",
spinner: 'el-icon-loading',
background: "rgba(0,0,0,.8)"
})
this.instance.post(`/app/wxcp/wxdepartment/syncDepart`).then(res => {
if (res?.code == 0) {
this.$message.success('同步成功')
this.getTree()
}
}).finally(() => loading.close())
}
},
created() {
this.dict.load('wxUserStatus')

View File

@@ -120,7 +120,7 @@
</el-form-item>
<el-form-item label="系统配置信息" prop="systemInfo">
<el-input type="textarea" :rows="2" placeholder="请输入系统配置信息" v-model="dialogForm.systemInfo"
maxlength="200"></el-input>
maxlength="50000"/>
</el-form-item>
</el-form>
</ai-dialog>

View File

@@ -1,8 +1,11 @@
{
"name": "cw-core-webapps",
"name": "dvcp-core",
"description": "系统业务模块",
"version": "1.0.13",
"main": "dist/cw-core-webapps.common.js",
"main": "dist/dvcp-core.common.js",
"files": [
"dist"
],
"publishConfig": {
"registry": "http://192.168.1.87:4873/"
}

View File

@@ -1,6 +1,6 @@
<template>
<div id="app">
<header-nav v-if="showTools" :title="serveName">
<header-nav v-if="showTools" title="web端产品库">
<template #right>
<div @click="showTools=false">隐藏工具栏</div>
<div @click="handleLogin">点此登录</div>
@@ -22,18 +22,13 @@
import SliderNav from "./components/sliderNav";
import MainContent from "./components/mainContent";
import HeaderNav from "./components/headerNav";
import {mapMutations, mapState} from "vuex";
export default {
name: 'app',
components: {HeaderNav, MainContent, SliderNav},
computed: {
serveName() {
let names = {
development: "村微产品库",
oms: "运营平台产品分库",
}
return names[process.env.NODE_ENV]
},
...mapState(['user']),
login() {
let url = '/auth/oauth/token';
/project\/sass/g.test(location.pathname) && (url += "?corpId=ww596787bb70f08288")
@@ -42,25 +37,24 @@ export default {
},
data() {
return {
token: "",
dialog: false,
showTools: true,
}
},
methods: {
setToken() {
localStorage.setItem('ui-token', this.token)
this.$message.success("设置token成功!")
},
...mapMutations(['setToken']),
getToken(params) {
this.token = params.access_token
this.setToken()
this.dialog = false
location.reload()
if (params.access_token) {
this.setToken([params.token_type, params.access_token].join(' '))
this.dialog = false
this.$message.success("登录成功,正在刷新页面...")
location.reload()
} else this.$message.error(params.msg || "登录失败!")
},
getUserInfo() {
this.$axios.post("/admin/user/detail-phone").then(res => {
if (res && res.data) {
if (res?.data) {
this.$store.commit("setUserInfo", res.data)
if (/^\/project\/xiushan/.test(location.pathname)) {
this.$store.commit("setFinanceUser")
@@ -69,21 +63,14 @@ export default {
})
},
handleLogin() {
this.$axios.delete("/auth/token/logout").then(() => {
this.$axios.delete("/auth/token/logout").finally(() => {
this.dialog = true
})
},
},
created() {
this.token = localStorage.getItem("ui-token")
if (this.token) this.getUserInfo()
if (this.user.token) this.getUserInfo()
wx = jWeixin
},
destroyed() {
this.token = ""
},
mounted() {
document.title = this.serveName
}
}
</script>

BIN
examples/assets/file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -11,7 +11,7 @@
<el-dropdown @visible-change="v=>isClick=v" @command="doMenu" class="rightDropdown">
<el-row type="flex" align="middle">
<el-avatar :src="user.info.avatar">
{{ user.info.name.slice(-2) }}
{{ defaultAvatar }}
</el-avatar>
<span>{{ [user.info.name, user.info.roleName].join(" - ") }}</span>
<i :class="dropdownIcon"/>
@@ -48,6 +48,9 @@ export default {
dropdownIcon() {
return this.isClick ? 'el-icon-caret-top' : 'el-icon-caret-bottom'
},
defaultAvatar() {
return this.user.info.name?.slice(-2) || "无名"
}
},
methods: {
// 获取最新的安卓、ios下载二维码

View File

@@ -6,7 +6,7 @@
<ai-empty>欢迎使用村微产品库</ai-empty>
</el-tab-pane>
<el-tab-pane v-for="op in tabs" :key="op.name" :closable="op.name!='工作台'" :name="op.name" :label="op.label" lazy>
<router-view/>
<router-view v-if="currentTab==op.name"/>
</el-tab-pane>
</el-tabs>
</section>
@@ -21,7 +21,7 @@ export default {
...mapState(['apps']),
currentTab() {
let {name, query, hash} = this.$route
return [name, query?.id, hash].join("")
return [name?.replace(query?.id, ''), query?.id, hash].join("") || "0"
}
},
data() {
@@ -32,43 +32,44 @@ export default {
watch: {
$route: {
immediate: true,
handler(v) {
this.getTabs(v)
handler() {
this.getTabs("route")
}
},
},
methods: {
handleTabClick(tab) {
let to = {}, selectedTab = this.tabs.find(e => e.name == tab.name)
if (selectedTab) {
to = {...selectedTab, params: {tabclick: 1}}
} else {
let {name, query, hash} = tab
to = {name, query, hash, params: {tabclick: 1}}
}
this.$router.push({...to})
handleTabClick({name}) {
let {name: route, query, hash} = this.tabs.find(e => e.name == name),
exps = []
query.id && exps.push(query.id)
hash && exps.push(hash)
let reg = new RegExp(`(${exps.join("|")})`, 'g')
this.$router.push({name: route.replace(reg, ''), query, hash})
},
handleTabRemove(id = this.currentTab) {
let tabs = JSON.parse(JSON.stringify(this.tabs)),
index = tabs?.findIndex(e => id == e.name)
if (id == this.currentTab) {
let next = tabs?.[index + 1] || tabs?.[index - 1]
this.handleTabClick(next)
next ? this.handleTabClick(next) : this.$router.push({path: '/'})
}
this.tabs.splice(index, 1)
},
getTabs() {
getTabs(from) {
let {name, query, hash} = this.$route
let tab = this.tabs.find(e => e.name == this.currentTab)
console.log(`getTabs>>>>>>>>>%s>>>>>>>%s`, from, name)
let tab = this.tabs.find(e => e.name == this.currentTab),
tabName = [name, query?.id, hash].join("")
if (tab) {
} else if (name) {
} else if (!name) {
} else if (tabName) {
let menu = this.apps.find(e => e.name == name)
this.tabs.push({name, query, hash, label: menu?.label})
this.tabs.push({name: tabName, query, hash, label: menu?.label})
}
},
},
created() {
this.getTabs()
this.getTabs("created")
}
}
</script>

View File

@@ -8,6 +8,7 @@
@click.stop="openKidMenu(item)">
<i class="prep-icon" :class="item.style||'iconfont iconloudongmoxing'"/>
<span class="menuName fill" v-text="item.label"/>
<el-badge type="warning" :hidden="!item.project" :value="item.project"/>
<i v-if="item.children" class="iconfont" :class="arrowIcon(item.showChildren)"/>
</div>
<div class="kidMenu" v-if="item.showChildren" @click.stop>
@@ -41,7 +42,14 @@ export default {
...mapState(['user', 'apps']),
navs() {
let reg = new RegExp(`.*${this.searchApp?.replace(/-/g,'')||''}.*`, 'gi')
return (this.apps || []).filter(e => !this.searchApp || reg?.test(e.name) || reg?.test(e.label))
return (this.apps || []).filter(e => !this.searchApp || reg?.test(e.name) || reg?.test(e.label)).map(e => {
if (/\/project\//.test(e.path)) {
e.project = e.path.replace(/.*project\/([^\/]+)\/.+/, '$1')
} else if (/\/core\//.test(e.path)) {
e.project = "core"
}
return e
})
},
isConsoleRoute() {
return this.$route.name == "工作台"
@@ -104,7 +112,7 @@ export default {
</script>
<style lang="scss" scoped>
.sliderNav {
width: 200px;
min-width: 200px;
height: 100%;
transition: width .1s;
display: flex;

View File

@@ -8,9 +8,12 @@ import vcUI from 'dvcp-ui';
import 'dvcp-ui/lib/styles/common.scss';
import 'dvcp-ui/lib/dvcp-ui.css';
import store from './store';
import dataV from '@jiaminghi/data-view';
import dvui from '../project/dvui/entries'
Vue.use(ui);
Vue.use(vcUI);
Vue.use(dvui)
//富文本编辑器配置
Vue.config.productionTip = false;
Vue.prototype.$axios = axios;

View File

@@ -2,6 +2,8 @@ import store from "../store";
import appEntry from "../views/appEntry";
import {waiting} from "../utils";
import router from "./router";
import axios from "./axios";
export default {
routes: [],
init() {
@@ -14,30 +16,29 @@ export default {
loadApps() {
//锁屏loading
waiting.init({innerHTML: '应用加载中..'})
//新App的自动化格式
let files = import.meta.glob('../../packages/**/App*.vue')
let cores = import.meta.glob('../../core/**/App*.vue')
let projects = import.meta.glob('../../project/**/App*.vue')
files = {...files, ...cores, ...projects}
return Promise.all(Object.keys(files).map(path => {
if (/App[A-Z]\w+\.vue/.test(path)) {
return files?.[path]()?.then(file => {
let {name, label} = file.default,
addApp = {
name: [path.replace(/[.\/]+(project)?[\/]([a-z]+).+/, '$2'), name].join("_"), label: label || name,
path: path.replace(/[.\/]+([a-zA-Z].+\/App[A-Z]\w+)\.vue$/, '/v/$1'),
component: appEntry,
module: file.default
}
//命名规范入口文件必须以App开头
waiting.setContent(`加载${name}...`)
router.addRoute(addApp)
this.routes.push(addApp)
return store.commit("addApp", addApp)
})
} else {
return Promise.resolve()
}
})).then(() => waiting.close())
let apps = require.context('../../', true, /\.(\/.+)\/App[A-Z][^\/]+\.vue$/, "lazy")
Promise.all(apps.keys().map(path => apps(path).then(file => {
if (file.default) {
let {name, label} = file.default,
addApp = {
name: path.replace(/\.\/?(vue)?/g, '')?.split("/").join("_"), label: label || name,
path: path.replace(/\.(\/.+\/App.+)\.vue$/, '$1'),
component: appEntry,
module: file.default
}
waiting.setContent(`加载${name}...`)
router.addRoute(addApp)
//命名规范入口文件必须以App开头
return store.commit("addApp", addApp)
} else return 0
}))).then(() => {
axios.post("/node/wechatapps/addOrUpdate", {
type: "web",
list: this.routes().map(({path: libPath, label, module: {name}, name: id}) => ({
id, type: 'web', libPath, label, name
}))
}, {baseURL: "/ns"}).catch(() => 0)
waiting.close()
})
}
}

View File

@@ -7,10 +7,11 @@ let baseURLs = {
oms: '/oms'
}
instance.defaults.baseURL = baseURLs[process.env.NODE_ENV]
instance.interceptors.request.eject(0);
instance.interceptors.request.use(config => {
if (config.url.startsWith("/node")) {
config.baseURL = "/ns"
} else if (/\/project\/beta/.test(location.pathname)) {
config.baseURL = "/wg"
} else if (/\/project\/sass/.test(location.pathname)) {
config.baseURL = "/saas"
} else if (/\/xiushan/.test(location.pathname)) {
@@ -19,9 +20,11 @@ instance.interceptors.request.use(config => {
} else if (/project\/oms/.test(location.pathname)) {
config.baseURL = "/omsapi"
config.url = config.url.replace(/(app|auth|admin)\//, "")
}
if (!config.withoutToken && localStorage.getItem("ui-token")) {
config.headers['Authorization'] = ["Bearer", localStorage.getItem("ui-token")].join(" ")
} else if (/#url-/.test(location.hash)) {
config.baseURL = location.hash.replace(/#url-/, '/')
if (["/xsjr", "/omsapi"].includes(config.baseURL)) {
config.url = config.url.replace(/(app|auth|admin)\//, "")
}
}
return config
}, error => Message.error(error))

View File

@@ -8,7 +8,7 @@ Vue.use(Vuex)
const user = {
state: {
info: {},
ATime: '',
token: '',
financeUser: {}
},
mutations: {
@@ -20,8 +20,8 @@ const user = {
setUserInfo(state, userInfo) {
state.info = userInfo
},
SET_TIME(state, pay) {
state.ATime = pay
setToken(state, token) {
state.token = token
}
}
}

View File

@@ -68,7 +68,9 @@ export const waiting = {
div.style.textAlign = 'center'
div.style.lineHeight = '100vh'
div.style.color = '#26f'
div.style.background = 'rgba(0,0,0,.8)'
div.style.fontSize = '20px'
div.style.background = 'rgba(255,255,255,.8)'
div.style.backdropFilter = 'blur(6px)'
document.body.appendChild(div)
} else if (count < 10) {
setTimeout(() => this.init(ops, ++count), 500)

View File

@@ -10,7 +10,7 @@
"lib:core": "vue-cli-service build --target lib --dest core/dist core/index.js --name vc-app-core&&npm unpublish --force&&npm publish",
"lib:project": "node project/build.js",
"lib:all": "node project/allProject.js&&npm unpublish --workspaces --force&&npm publish --workspaces",
"ui": "npm i dvcp-ui@latest dvcp-dv-ui@latest"
"ui": "npm i dvcp-ui@latest"
},
"workspaces": [
"project/*"

View File

@@ -0,0 +1,58 @@
<template>
<section class="preview">
<ai-dv-wrapper :views="[{label: '返回'}]" :theme="config.theme" @change="$router.back()" v-if="screenId" :title="info.name">
<ai-dv-background
:theme="config.theme"
v-if="config.length || config.theme === '1'"
:src="config.theme === '1' ? 'https://cdn.cunwuyun.cn/dvcp/dv/img/dj-bg.png' : config.backgroundImage[0].url">
</ai-dv-background>
<app-gigscreen-viewer :urlPrefix="urlPrefix" :instance="instance" :dict="dict" :id="screenId"/>
</ai-dv-wrapper>
</section>
</template>
<script>
import AppGigscreenViewer from "../../viewer/AppGigscreenViewer";
export default {
name: "preview",
components: {AppGigscreenViewer},
props: {
instance: Function,
dict: Object,
permissions: Function,
urlPrefix: {
type: String,
default: '/app'
}
},
computed: {
screenId: v => v.$route.query.id
},
data() {
return {
info: {},
config: {}
}
},
methods: {
getDvData() {
let {id} = this.$route.query
this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenDetailById?id=${id}`).then(res => {
if (res?.data) {
this.info = res.data
this.config = JSON.parse(res.data.config).dashboard
}
})
}
},
created() {
this.getDvData()
}
}
</script>
<style lang="scss" scoped>
.preview {
}
</style>

View File

@@ -0,0 +1,87 @@
<template>
<ai-list class="AppDeviceConfig">
<template slot="title">
<ai-title title="设备配置" :isShowBottomBorder="false" :fullname.sync="areaName" v-model="areaId" :instance="instance" @change="onAreaChange"></ai-title>
</template>
<template slot="tabs">
<el-tabs v-model="currIndex">
<el-tab-pane v-for="(tab,i) in tabs" :key="i" :label="tab.label">
<component :areaId="areaId" :ref="String(i)" v-if="currIndex == i" :is="tab.comp" @change="onChange" lazy :instance="instance" :dict="dict" :permissions="permissions"/>
</el-tab-pane>
</el-tabs>
</template>
</ai-list>
</template>
<script>
import eyeList from './components/eyeList.vue'
import videoList from './components/videoList.vue'
import { mapState } from 'vuex'
export default {
name: 'AppDeviceConfig',
label: '设备配置',
components: {
eyeList,
videoList,
},
props: {
instance: Function,
dict: Object,
permissions: Function
},
computed: {
...mapState(['user']),
tabs () {
const tabList = [
{label: '千里眼', name: 'eyeList', comp: eyeList, permission: ''},
{label: '视联网', name: 'videoList', comp: videoList, permission: ''}
]
return tabList
}
},
data () {
return {
currIndex: '0',
component: 'eyeList',
params: {},
areaId: '',
areaName: ''
}
},
created () {
this.areaId = this.user.info.areaId
},
methods: {
onChange (data) {
this.component = data.type
this.params = data.params
this.$nextTick(() => {
if (data.isRefresh) {
this.$refs.component.getList()
}
})
},
onAreaChange () {
this.$refs[this.currIndex][0].changeArea()
}
}
}
</script>
<style lang="scss" scoped>
.AppDeviceConfig {
height: 100%;
}
</style>

View File

@@ -0,0 +1,237 @@
<template>
<ai-list class="eyeList" isTabs>
<template slot="content">
<ai-search-bar bottomBorder>
<template #left>
<el-button type="primary" icon="iconfont iconAdd" size="small" @click="add('添加设备配置', {})">添加</el-button>
<el-button icon="el-icon-delete" class="delete-btn del-btn-list" :disabled="!ids.length" @click="remove(ids)">删除</el-button>
</template>
<template slot="right">
<el-input
v-model="search.condition"
class="search-input"
size="small"
v-throttle="() => {search.current = 1, getList()}"
placeholder="请输入CorpId"
clearable
@change="getList"
@clear="search.current = 1, search.condition = '', getList()"
suffix-icon="iconfont iconSearch">
</el-input>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
v-loading="loading"
style="margin-top: 16px;"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList"
@selection-change="v=>ids=v.map(e=>e.id)">
<el-table-column slot="options" width="140px" fixed="right" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="edit('编辑设备配置', row)">编辑</el-button>
<el-button type="text" @click="refresh(row)">刷新</el-button>
<el-button type="text" @click="remove(row.id)">删除</el-button>
</div>
</template>
</el-table-column>
<el-table-column slot="flag" align="center" label="状态" width="100">
<template v-slot="{ row }">
<el-switch v-model="row.flag" @change="onChange(row)" active-value="1" inactive-value="0"
active-color="#5088FF" inactive-color="#D0D4DC"></el-switch>
</template>
</el-table-column>
</ai-table>
<ai-dialog :title="dialogTitle" :visible.sync="dialog" width="800px" @onConfirm="addForm" @closed="dialogForm={}">
<el-form ref="addForm" :model="dialogForm" :rules="rules" size="small" label-width="160px">
<el-form-item label="CorpId" prop="corpId">
<el-input v-model.trim="dialogForm.corpId" placeholder="请输入..." clearable :maxLength="50"/>
</el-form-item>
<el-form-item required label="状态">
<el-radio-group v-model="dialogForm.flag">
<el-radio :label="0">关闭</el-radio>
<el-radio :label="1">开启</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="AppId">
<el-input v-model.trim="dialogForm.appId" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="RSA">
<el-input v-model.trim="dialogForm.rsa" placeholder="请输入..." clearable :maxLength="500" type="textarea" :rows="5"/>
</el-form-item>
<el-form-item label="SECRET">
<el-input v-model.trim="dialogForm.secret" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="TOKEN">
<el-input v-model.trim="dialogForm.token" placeholder="请输入..." clearable :maxLength="200" type="textarea" :rows="2"/>
</el-form-item>
<el-form-item label="结点ids">
<el-input v-model.trim="dialogForm.orgIds" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="版本号">
<el-input v-model.trim="dialogForm.version" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="大喇叭账号">
<el-input v-model.trim="dialogForm.dlbName" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="大喇叭密码">
<el-input v-model.trim="dialogForm.dlbPwd" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="大喇叭Token">
<el-input v-model.trim="dialogForm.dlbToken" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
</el-form>
</ai-dialog>
</template>
</ai-list>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'eyeList',
props: {
instance: Function,
dict: Object,
areaId: String
},
data () {
return {
search: {
current: 1,
condition: '',
size: 10,
},
ids: [],
tableData: [],
total: 0,
loading: false,
dialog: false,
dialogTitle: '',
dialogForm: {}
}
},
computed: {
...mapState(['user']),
param () {
return this.search
},
rules() {
return {
corpId: [{required: true, message: "请输入CorpId"}],
}
},
colConfigs() {
return [
{type: "selection"},
{ prop: 'corpId', label: 'CorpId', fixed: 'left', width: 220 },
{ slot: 'flag', align: 'center', label: '状态', fixed: 'left', width: 120 },
{ prop: 'appId', align: 'center', label: 'AppId', width: 240 },
{ prop: 'rsa', align: 'center', label: 'RSA', width: 240 },
{ prop: 'secret', align: 'center', label: 'SECRET', width: 180 },
{ prop: 'token', align: 'center', label: 'TOKEN', width: 120 },
{ prop: 'orgIds', align: 'center', label: '结点ids', width: 120 },
{ prop: 'version', align: 'center', label: '版本号', width: 120 },
{ prop: 'dlbName', align: 'center', label: '大喇叭账号', width: 140 },
{ prop: 'dlbPwd', align: 'center', label: '大喇叭密码', width: 140 },
{ prop: 'dlbToken', align: 'center', label: '大喇叭Token', width: 180 },
{ prop: 'createTime', align: 'center', label: '创建时间', fixed: 'right', width: 180 },
{ slot: 'options'},
]
}
},
created () {
this.getList()
},
methods: {
getListInit() {
this.search.current = 1
this.getList()
},
getList () {
this.instance.post(`/app/appzyaccountconfig/list`, null, {
params: {
...this.search,
type: 0
}
}).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
})
},
remove(id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appzyaccountconfig/delete?ids=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
})
},
add(title, item) {
this.dialog = true
this.dialogTitle = title
this.dialogForm = item
if(title == '添加设备配置') {
this.dialogForm.flag = 1
this.dialogForm.version = '1.0.0'
}
},
addForm() {
this.$refs.addForm.validate((valid) => {
if (valid) {
this.dialogForm.type = 0
this.instance.post(`/app/appzyaccountconfig/addOrUpdate`, this.dialogForm).then((res) => {
if (res.code == 0) {
this.$message.success(`${this.dialogForm.id ? '编辑成功' : '添加成功'}`)
this.getListInit()
this.dialog = false;
}
});
} else {
return false;
}
});
},
refresh(row) {
this.$confirm('确定刷新该数据token').then(() => {
this.instance.post(`/app/appzyaccountconfig/initQlyToken?id=${row.id}`).then(res => {
if (res.code == 0) {
this.$message.success('刷新成功!')
this.getList()
}
})
})
},
onChange(row) {
this.instance.post(`/app/appzyaccountconfig/setFlag`, null, {
params: {
id: row.id,
flag: row.flag
}
}).then((res) => {
if (res.code == 0) {
this.$message.success(+row.flag ? '已启用' : '已禁用');
this.getList();
}
})
},
}
}
</script>

View File

@@ -0,0 +1,224 @@
<template>
<ai-list class="videoList" isTabs>
<template slot="content">
<ai-search-bar bottomBorder>
<template #left>
<el-button type="primary" icon="iconfont iconAdd" size="small" @click="add('添加设备配置', {})">添加</el-button>
<el-button icon="el-icon-delete" class="delete-btn del-btn-list" :disabled="!Boolean(ids.length)" @click="remove(ids)">删除</el-button>
</template>
<template #right>
<el-input
v-model="search.condition"
class="search-input"
size="small"
v-throttle="() => {search.current = 1, getList()}"
placeholder="请输入CorpId"
clearable
@change="getList"
@clear="search.current = 1, search.condition = '', getList()"
suffix-icon="iconfont iconSearch">
</el-input>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
v-loading="loading"
style="margin-top: 16px;"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList"
@selection-change="v=>ids=v.map(e=>e.id)">
<el-table-column slot="options" width="140px" fixed="right" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="edit('编辑设备配置', row)">编辑</el-button>
<el-button type="text" @click="refresh(row)">刷新</el-button>
<el-button type="text" @click="remove(row.id)">删除</el-button>
</div>
</template>
</el-table-column>
<el-table-column slot="flag" align="center" label="状态" width="100">
<template v-slot="{ row }">
<el-switch v-model="row.flag" @change="onChange(row)" active-value="1" inactive-value="0"
active-color="#5088FF" inactive-color="#D0D4DC"></el-switch>
</template>
</el-table-column>
</ai-table>
<ai-dialog :title="dialogTitle" :visible.sync="dialog" width="800px" @onConfirm="addForm" @closed="dialogForm={}">
<el-form ref="addForm" :model="dialogForm" :rules="rules" size="small" label-width="160px">
<el-form-item label="CorpId" prop="corpId">
<el-input v-model.trim="dialogForm.corpId" placeholder="请输入..." clearable :maxLength="50"/>
</el-form-item>
<el-form-item required label="状态">
<el-radio-group v-model="dialogForm.flag">
<el-radio :label="0">关闭</el-radio>
<el-radio :label="1">开启</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="用户ID">
<el-input v-model.trim="dialogForm.slwUserId" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="地区编码">
<el-input v-model.trim="dialogForm.slwAreaId" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="TOKEN">
<el-input v-model.trim="dialogForm.slwToken" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="大喇叭账号">
<el-input v-model.trim="dialogForm.dlbName" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="大喇叭密码">
<el-input v-model.trim="dialogForm.dlbPwd" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
<el-form-item label="大喇叭Token">
<el-input v-model.trim="dialogForm.dlbToken" placeholder="请输入..." clearable :maxLength="50" />
</el-form-item>
</el-form>
</ai-dialog>
</template>
</ai-list>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'eyeList',
props: {
instance: Function,
dict: Object,
areaId: String
},
data () {
return {
search: {
current: 1,
condition: '',
size: 10,
},
ids: [],
tableData: [],
total: 0,
loading: false,
dialog: false,
dialogTitle: '',
dialogForm: {}
}
},
computed: {
...mapState(['user']),
param () {
return this.search
},
rules() {
return {
corpId: [{required: true, message: "请输入CorpId"}],
}
},
colConfigs() {
return [
{type: "selection"},
{ prop: 'corpId', label: 'CorpId', fixed: 'left', width: 220 },
{ slot: 'flag', align: 'center', label: '状态', fixed: 'left', width: 120 },
{ prop: 'slwUserId', align: 'center', label: '用户ID', width: 180 },
{ prop: 'slwAreaId', align: 'center', label: '地区编码', width: 180 },
{ prop: 'slwToken', align: 'center', label: 'TOKEN', width: 220 },
{ prop: 'dlbName', align: 'center', label: '大喇叭账号', width: 140 },
{ prop: 'dlbPwd', align: 'center', label: '大喇叭密码', width: 140 },
{ prop: 'dlbToken', align: 'center', label: '大喇叭Token', width: 180 },
{ prop: 'createTime', align: 'center', label: '创建时间', width: 180 },
{ slot: 'options'},
]
}
},
created () {
this.getList()
},
methods: {
getListInit() {
this.search.current = 1
this.getList()
},
getList () {
this.instance.post(`/app/appzyaccountconfig/list`, null, {
params: {
...this.search,
type: 1
}
}).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
})
},
remove(id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appzyaccountconfig/delete?ids=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
})
},
add(title, item) {
this.dialog = true
this.dialogTitle = title
this.dialogForm = item
if(title == '添加设备配置') {
this.dialogForm.flag = 1
}
},
addForm() {
this.$refs.addForm.validate((valid) => {
if (valid) {
this.dialogForm.type = 1
this.instance.post(`/app/appzyaccountconfig/addOrUpdate`, this.dialogForm).then((res) => {
if (res.code == 0) {
this.$message.success(`${this.dialogForm.id ? '编辑成功' : '添加成功'}`)
this.getListInit()
this.dialog = false;
}
});
} else {
return false;
}
});
},
refresh(row) {
this.$confirm('确定刷新该数据token').then(() => {
this.instance.post(`/app/appzyaccountconfig/initSlwToken?id=${row.id}`).then(res => {
if (res.code == 0) {
this.$message.success('刷新成功!')
this.getList()
}
})
})
},
onChange(row) {
this.instance.post(`/app/appzyaccountconfig/setFlag`, null, {
params: {
id: row.id,
flag: row.flag
}
}).then((res) => {
if (res.code == 0) {
this.$message.success(+row.flag ? '已启用' : '已禁用');
this.getList();
}
})
}
}
}
</script>

View File

@@ -1,72 +1,54 @@
<template>
<div class="doc-circulation ailist-wrapper">
<keep-alive :include="['List']">
<component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component>
</keep-alive>
</div>
<section class="AppReportAtWill">
<component ref="component" :is="currentPage" @change="onChange" :params="params" :instance="instance" :dict="dict"/>
</section>
</template>
<script>
import List from './components/List'
import Detail from './components/Detail'
import Setting from './components/Setting'
import List from './components/List'
import Detail from './components/Detail'
import Setting from './components/Setting'
export default {
name: 'AppReportAtWill',
label: '随手拍',
export default {
name: 'AppReportAtWill',
label: '随手拍',
props: {
instance: Function,
dict: Object
},
props: {
instance: Function,
dict: Object
},
data () {
return {
component: 'List',
params: {}
}
},
data() {
return {
component: 'List',
params: {}
}
},
computed: {
currentPage() {
let {hash, query: {id}} = this.$route
return hash == "#Setting" ? Setting :
!!id ? Detail : List
}
},
components: {
List,
Detail,
Setting
},
components: {
List,
Detail,
Setting
},
mounted () {
},
methods: {
onChange (data) {
if (data.type === 'Detail') {
this.component = 'Detail'
this.params = data.params
}
if (data.type === 'Setting') {
this.component = 'Setting'
this.params = data.params
}
if (data.type === 'list') {
this.component = 'List'
this.params = data.params
this.$nextTick(() => {
if (data.isRefresh) {
this.$refs.component.getList()
}
})
}
}
methods: {
onChange(data) {
this.$router.push({query: data.params, hash: data.type == "Setting" ? "#Setting" : ""})
}
}
}
</script>
<style lang="scss">
.doc-circulation {
height: 100%;
background: #F3F6F9;
overflow: auto;
}
.AppReportAtWill {
height: 100%;
background: #F3F6F9;
overflow: auto;
}
</style>

View File

@@ -1,7 +1,7 @@
<template>
<ai-detail class="reportAtWillDetail" v-loading="isLoading">
<template #title>
<ai-title title="随手拍详情" isShowBack isShowBottomBorder @onBackClick="cancel(false)">
<ai-title title="随手拍详情" isShowBack isShowBottomBorder @onBackClick="cancel(false)">
<template #rightBtn>
<div class="title-btns">
<el-button type="primary" icon="iconfont iconPerson_Transfered" @click="isShowForward = true" v-if="detail.eventStatus < 2">指派事件</el-button>
@@ -36,10 +36,10 @@
<template #content>
<el-steps direction="vertical" :active="1">
<el-step
v-for="(item, i) in processList"
:key="i"
:title="item.systemExplain"
:description="item.doTime">
v-for="(item, i) in processList"
:key="i"
:title="item.systemExplain"
:description="item.doTime">
<template #title>
<h2 class="step-title" style="font-weight: 500; font-size: 14px;">
{{ item.systemExplain }}
@@ -57,17 +57,17 @@
</div>
</div>
<ai-dialog
:visible.sync="isShowAdd"
width="800px"
title="事件处理"
@closed="onClose"
@onConfirm="handleEvent">
:visible.sync="isShowAdd"
width="800px"
title="事件处理"
@closed="onClose"
@onConfirm="handleEvent">
<el-form class="ai-form" label-width="120px" :model="form" ref="form">
<el-form-item label="事件分类" prop="groupId" style="width: 100%;" :rules="[{ required: true, message: '请选择事件分类' }]">
<ai-select
v-model="form.groupId"
placeholder="请选择事件分类"
:selectList="dictList">
v-model="form.groupId"
placeholder="请选择事件分类"
:selectList="dictList">
</ai-select>
</el-form-item>
<el-form-item label="处理结果" prop="eventStatus" style="width: 100%;" :rules="[{ required: true, message: '请选择处理结果' }]">
@@ -81,25 +81,25 @@
</el-form-item>
<el-form-item label="图片" prop="files" style="width: 100%;">
<ai-uploader
:instance="instance"
isShowTip
v-model="form.files"
:limit="9">
:instance="instance"
isShowTip
v-model="form.files"
:limit="9">
</ai-uploader>
</el-form-item>
</el-form>
</ai-dialog>
<ai-dialog
:visible.sync="isShowForward"
width="800px"
@close="onClose"
title="事件指派"
@onConfirm="onForwardConfirm">
:visible.sync="isShowForward"
width="800px"
@close="onClose"
title="事件指派"
@onConfirm="onForwardConfirm">
<el-form class="ai-form" label-width="120px" :model="forwardForm" ref="forwardForm">
<el-form-item label="转交" prop="name" style="width: 100%;" :rules="[{ required: true, message: '请选择网格员或网格' }]">
<el-input disabled size="small" v-model="forwardForm.name" clearable placeholder="请选择网格员或网格">
<template slot="append">
<el-button @click="isShowUser = true">选择</el-button>
<el-button @click="getGirdList().then(()=>isShowUser=true )">选择</el-button>
</template>
</el-input>
</el-form-item>
@@ -108,35 +108,35 @@
</el-form-item>
<el-form-item label="图片" prop="files" style="width: 100%;">
<ai-uploader
:instance="instance"
v-model="forwardForm.files"
isShowTip
:limit="9">
:instance="instance"
v-model="forwardForm.files"
isShowTip
:limit="9">
</ai-uploader>
</el-form-item>
</el-form>
</ai-dialog>
<ai-dialog
:visible.sync="isShowUser"
width="800px"
title="选择网格或网格员"
@onConfirm="onConfirm">
:visible.sync="isShowUser"
width="800px"
title="选择网格或网格员"
@onConfirm="onConfirm">
<div class="grid-wrapper">
<el-input
style="margin-bottom: 10px;"
size="small"
placeholder="请输入网格名称/网格员姓名/网格员电话"
v-model="name"
suffix-icon="iconfont iconSearch">
style="margin-bottom: 10px;"
size="small"
placeholder="请输入网格名称/网格员姓名/网格员电话"
v-model="name" @change="$refs.tree.filter(name)"
suffix-icon="iconfont iconSearch">
</el-input>
<el-tree
:filter-node-method="filterNode"
ref="tree"
:props="defaultProps"
node-key="id"
:data="tree"
highlight-current
@current-change="onTreeChange">
:filter-node-method="filterNode"
ref="tree"
:props="defaultProps"
node-key="id"
:data="tree"
highlight-current
@current-change="onTreeChange">
<div class="tree-container" slot-scope="{ data }">
<div class="tree-container__user">
<div class="tree-user__item">
@@ -152,451 +152,421 @@
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader'
import { mapState } from 'vuex'
import AMapLoader from '@amap/amap-jsapi-loader'
import {mapState} from 'vuex'
export default {
name: 'Detail',
props: ['dict', 'instance', 'params'],
export default {
name: 'Detail',
props: ['dict', 'instance'],
data() {
return {
forwardForm: {
content: '',
girdId: '',
girdName: '',
girdMemberId: '',
girdMemberName: '',
name: ''
},
isLoading: true,
name: '',
detail: {},
isShowUser: false,
eventList: [],
isShowAdd: false,
userList: [],
processList: [],
dictList: [],
defaultProps: {
children: 'girdList',
label: 'girdName'
},
isShowForward: false,
tree: [],
gridInfo: {},
form: {
files: [],
groupId: '',
groupName: '',
content: [],
eventStatus: '2'
data() {
return {
forwardForm: {
content: '',
girdId: '',
girdName: '',
girdMemberId: '',
girdMemberName: '',
name: ''
},
isLoading: true,
name: '',
detail: {},
isShowUser: false,
eventList: [],
isShowAdd: false,
userList: [],
processList: [],
dictList: [],
defaultProps: {
label: 'girdName'
},
isShowForward: false,
tree: [],
gridInfo: {},
form: {
files: [],
groupId: '',
groupName: '',
content: [],
eventStatus: '2'
}
}
},
computed: {
...mapState(['user'])
},
created() {
this.getDict()
this.dict.load('clapEventStatus').then(() => {
this.getDetail()
})
},
methods: {
getDetail() {
this.instance.post('/app/appclapeventinfo/queryDetailById', null, {
params: {id: this.$route.query.id}
}).then(res => {
if (res?.data) {
this.detail = res.data
this.processList = res.data.processList
this.form.groupId = res.data.groupId
this.$nextTick(() => {
this.initMap()
})
this.isLoading = false
}
}
},
computed: {
...mapState(['user'])
},
watch: {
name (val) {
this.$refs.tree.filter(val)
}
},
created() {
this.getDict()
this.getGirdList()
this.dict.load('clapEventStatus').then(() => {
this.getDetail()
}).catch(() => {
this.isLoading = false
})
},
methods: {
getDetail() {
this.instance.post('/app/appclapeventinfo/queryDetailById', null, {
params: { id: this.params.id }
}).then(res => {
if (res?.data) {
this.detail = res.data
this.processList = res.data.processList
this.form.groupId = res.data.groupId
this.$nextTick(() => {
this.initMap()
})
this.isLoading = false
}
}).catch(() => {
this.isLoading = false
})
},
getGirdList () {
this.instance.post(`/app/appgirdinfo/listAllByTop`).then(res => {
if (res.code == 0) {
this.tree = this.formatList(res.data)
}
})
},
onClose () {
this.form.files = []
this.form.groupId = ''
this.form.groupName = ''
this.form.content = ''
this.form.eventStatus = ''
this.forwardForm.content = ''
this.forwardForm.girdId = ''
this.forwardForm.girdName = ''
this.forwardForm.girdMemberId = ''
this.forwardForm.girdMemberName = ''
this.forwardForm.name = ''
},
formatList (list) {
var arr = []
for (let item of list) {
if (item.girdMemberList && item.girdMemberList.length) {
let userList = JSON.parse(JSON.stringify(item.girdMemberList)).map(v => {
return {
...v,
isUser: true,
girdName: item.girdName,
girdId: item.id
}
})
item.girdList = [
...userList
]
delete item.girdMemberList
}
if (item.girdList && item.girdList.length) {
this.formatList(item.girdList)
}
arr.push(item)
getGirdList() {
return this.instance.post(`/app/appgirdinfo/listAllByTop`).then(res => {
if (res?.data) {
return this.tree = this.formatList([res.data])
}
})
},
return arr
},
onClose() {
this.form.files = []
this.form.groupId = ''
this.form.groupName = ''
this.form.content = ''
this.form.eventStatus = ''
this.forwardForm.content = ''
this.forwardForm.girdId = ''
this.forwardForm.girdName = ''
this.forwardForm.girdMemberId = ''
this.forwardForm.girdMemberName = ''
this.forwardForm.name = ''
},
filterNode (value, data) {
if (!value) return true
return (data.girdName && data.girdName.indexOf(value) !== -1) || (data.name && data.name.indexOf(value) !== -1) || (data.name && data.phone.indexOf(value) !== -1)
},
onTreeChange (e) {
this.gridInfo = e
},
onForwardConfirm () {
this.$refs.forwardForm.validate(v => {
if (v) {
this.instance.post('/app/appclapeventinfo/transferByManager', {
...this.forwardForm,
id: this.params.id
}).then(res => {
if (res?.code == 0) {
this.isShowForward = false
this.getDetail()
this.$message.success('转交成功!')
}
})
}
})
},
onConfirm () {
if (this.gridInfo.userId || this.gridInfo.girdLevel === '2') {
if (this.gridInfo.userId) {
this.forwardForm.girdId = this.gridInfo.girdId
this.forwardForm.girdName = this.gridInfo.girdName
this.forwardForm.girdMemberId = this.gridInfo.id
this.forwardForm.girdMemberName = this.gridInfo.name
} else {
this.forwardForm.girdId = this.gridInfo.id
}
this.forwardForm.girdName = this.gridInfo.girdName
this.forwardForm.name = `${this.gridInfo.girdName}${this.gridInfo.name ? '-' + this.gridInfo.name : ''}`
this.isShowUser = false
} else {
return this.$message.error('请选择网格员或者最后层网格')
formatList(list) {
for (let item of list) {
item.children = [item.girdList, item.girdMemberList?.map(e => ({
...e, isUser: true, girdName: item.girdName,
girdId: item.id
})) || []].flat()
if (item.girdList?.length > 0) {
this.formatList(item.girdList)
}
},
}
return list
},
getDict () {
this.instance.post(`/app/appclapeventgroup/list?current=1&size=100000`).then(res => {
if (res.code == 0) {
this.dictList = res.data.records.map(v => {
return {
dictValue: v.id,
dictName: v.groupName
}
})
}
})
},
filterNode(value, data) {
if (!value) return true
close () {
this.$confirm('确定关闭该事件?').then(() => {
this.instance.post(`/app/appmininotice/delete?ids=${this.params.id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
return (data.girdName && data.girdName.indexOf(value) !== -1) || (data.name && data.name.indexOf(value) !== -1) || (data.name && data.phone.indexOf(value) !== -1)
},
onTreeChange(e) {
this.gridInfo = e
},
onForwardConfirm() {
this.$refs.forwardForm.validate(v => {
if (v) {
this.instance.post('/app/appclapeventinfo/transferByManager', {
...this.forwardForm,
id: this.$route.query.id
}).then(res => {
if (res?.code == 0) {
this.isShowForward = false
this.getDetail()
this.$message.success('转交成功!')
}
})
})
},
}
})
},
cancel (isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh
})
},
onChange(e) {
this.instance.post(`/app/appvillagerintegralrule/list?size=1000&classification=${e}&ruleStatus=1`).then(res => {
if (res.code === 0) {
this.form.ruleId = ''
this.eventList = res.data.records
}
})
},
initMap() {
let { lng, lat } = this.detail
let center = [lng, lat]
AMapLoader.load({
key: 'b553334ba34f7ac3cd09df9bc8b539dc',
version: '2.0'
}).then(AMap => {
let map = new AMap.Map('map', {
center,
zoom: 14
})
let marker = new AMap.Marker({
position: new AMap.LngLat(lng, lat),
title: this.detail.address
})
map.add(marker)
})
},
handleEvent() {
this.$refs.form.validate(v => {
if (v) {
this.instance.post('/app/appclapeventinfo/finishByManager', {
...this.form,
groupName: this.dictList.filter(v => v.dictValue === this.form.groupId)[0].dictName,
id: this.params.id
}).then(res => {
if (res?.code == 0) {
this.isShowAdd = false
this.getDetail()
this.$message.success('处理成功!')
}
})
}
})
onConfirm() {
if (this.gridInfo.userId) {
this.forwardForm.girdId = this.gridInfo.girdId
this.forwardForm.girdName = this.gridInfo.girdName
this.forwardForm.girdMemberId = this.gridInfo.id
this.forwardForm.girdMemberName = this.gridInfo.name
} else {
this.forwardForm.girdId = this.gridInfo.id
}
this.forwardForm.girdName = this.gridInfo.girdName
this.forwardForm.name = `${this.gridInfo.girdName}${this.gridInfo.name ? '-' + this.gridInfo.name : ''}`
this.isShowUser = false
},
getDict() {
this.instance.post(`/app/appclapeventgroup/list?current=1&size=100000`).then(res => {
if (res.code == 0) {
this.dictList = res.data.records.map(v => {
return {
dictValue: v.id,
dictName: v.groupName
}
})
}
})
},
close() {
this.$confirm('确定关闭该事件?').then(() => {
this.instance.post(`/app/appmininotice/delete?ids=${this.$route.query.id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
})
},
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh
})
},
onChange(e) {
this.instance.post(`/app/appvillagerintegralrule/list?size=1000&classification=${e}&ruleStatus=1`).then(res => {
if (res.code === 0) {
this.form.ruleId = ''
this.eventList = res.data.records
}
})
},
initMap() {
let {lng, lat} = this.detail
let center = [lng, lat]
AMapLoader.load({
key: 'b553334ba34f7ac3cd09df9bc8b539dc',
version: '2.0'
}).then(AMap => {
let map = new AMap.Map('map', {
center,
zoom: 14
})
let marker = new AMap.Marker({
position: new AMap.LngLat(lng, lat),
title: this.detail.address
})
map.add(marker)
})
},
handleEvent() {
this.$refs.form.validate(v => {
if (v) {
this.instance.post('/app/appclapeventinfo/finishByManager', {
...this.form,
groupName: this.dictList.filter(v => v.dictValue === this.form.groupId)[0].dictName,
id: this.$route.query.id
}).then(res => {
if (res?.code == 0) {
this.isShowAdd = false
this.getDetail()
this.$message.success('处理成功!')
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.reportAtWillDetail {
height: 100%;
.reportAtWillDetail {
height: 100%;
.grid-wrapper {
min-height: 360px;
.grid-wrapper {
min-height: 360px;
}
.title-btns {
display: flex;
align-items: center;
}
::v-deep .el-tree {
background: transparent;
.el-tree-node__expand-icon.is-leaf {
color: transparent !important;
}
.title-btns {
display: flex;
align-items: center;
}
::v-deep .el-tree {
background: transparent;
.el-tree-node__expand-icon.is-leaf {
color: transparent !important;
}
.el-tree-node__content > .el-tree-node__expand-icon {
padding: 4px;
}
.el-tree-node__content {
height: 32px;
}
.el-tree__empty-text {
color: #222;
font-size: 14px;
}
.el-tree-node__children .el-tree-node__content {
height: 32px;
}
.el-tree-node__content:hover {
background: #E8EFFF;
color: #222222;
border-radius: 2px;
}
.is-current > .el-tree-node__content {
&:hover {
background: #2266FF;
color: #fff;
}
background: #2266FF;
span {
color: #fff;
}
}
}
.el-steps {
::v-deep .el-step__icon {
font-size: 12px;
color: #555555;
border-color: #d0d4dc;
}
::v-deep .el-step__head.is-finish {
.el-step__icon.is-text {
border: none;
color: #fff;
font-size: 12px;
background: #2266ff;
}
}
::v-deep .el-step__line {
background-color: #d0d4dc;
}
.el-tree-node__content > .el-tree-node__expand-icon {
padding: 4px;
}
.imgs {
font-size: 0;
img {
width: 108px;
height: 108px;
margin-right: 4px;
margin-bottom: 4px;
cursor: pointer;
user-select: none;
&:hover {
opacity: 0.8;
}
&:nth-of-type(2n) {
margin-right: 0;
}
}
.el-tree-node__content {
height: 32px;
}
::v-deep .report-dialog {
.el-select {
width: 100%;
}
.el-tree__empty-text {
color: #222;
font-size: 14px;
}
::v-deep .el-step__head.is-process {
color: #555;
border-color: #555;
.el-tree-node__children .el-tree-node__content {
height: 32px;
}
::v-deep .is-finish h2 {
color: #2266ff;
.el-tree-node__content:hover {
background: #E8EFFF;
color: #222222;
border-radius: 2px;
}
.step-title {
color: #555;
}
.detail-content__wrapper {
display: flex;
width: 100%;
.detail-content__wrapper--left {
flex: 1;
margin-right: 20px;
}
}
::v-deep .ai-detail__content {
background: #f3f6f9;
.ai-detail__content--wrapper {
display: flex;
gap: 16px;
width: 100%;
max-width: 100%;
padding: 16px;
box-sizing: border-box;
& > .el-card {
flex: 1;
min-width: 0;
}
.rightZone {
width: 400px;
flex-shrink: 0;
display: flex;
flex-direction: column;
gap: 16px;
}
}
}
::v-deep .el-card {
.el-card__header {
padding: 12px 16px;
font-weight: bold;
.is-current > .el-tree-node__content {
&:hover {
background: #2266FF;
color: #fff;
}
.el-card__body {
padding: 8px;
}
background: #2266FF;
#amap {
width: 466px;
height: 232px;
}
.el-steps {
margin-left: 8px;
}
.imgFormItem > .el-form-item__content {
display: flex;
gap: 16px;
flex-wrap: wrap;
&:before {
content: none;
}
.el-image__inner {
width: 82px;
height: 82px;
}
span {
color: #fff;
}
}
}
.el-steps {
::v-deep .el-step__icon {
font-size: 12px;
color: #555555;
border-color: #d0d4dc;
}
::v-deep .el-step__head.is-finish {
.el-step__icon.is-text {
border: none;
color: #fff;
font-size: 12px;
background: #2266ff;
}
}
::v-deep .el-step__line {
background-color: #d0d4dc;
}
}
.imgs {
font-size: 0;
img {
width: 108px;
height: 108px;
margin-right: 4px;
margin-bottom: 4px;
cursor: pointer;
user-select: none;
&:hover {
opacity: 0.8;
}
&:nth-of-type(2n) {
margin-right: 0;
}
}
}
::v-deep .report-dialog {
.el-select {
width: 100%;
}
}
::v-deep .el-step__head.is-process {
color: #555;
border-color: #555;
}
::v-deep .is-finish h2 {
color: #2266ff;
}
.step-title {
color: #555;
}
.detail-content__wrapper {
display: flex;
width: 100%;
.detail-content__wrapper--left {
flex: 1;
margin-right: 20px;
}
}
::v-deep .ai-detail__content {
background: #f3f6f9;
.ai-detail__content--wrapper {
display: flex;
gap: 16px;
width: 100%;
max-width: 100%;
padding: 16px;
box-sizing: border-box;
& > .el-card {
flex: 1;
min-width: 0;
}
.rightZone {
width: 400px;
flex-shrink: 0;
display: flex;
flex-direction: column;
gap: 16px;
}
}
}
::v-deep .el-card {
.el-card__header {
padding: 12px 16px;
font-weight: bold;
}
.el-card__body {
padding: 8px;
}
#amap {
width: 466px;
height: 232px;
}
.el-steps {
margin-left: 8px;
}
.imgFormItem > .el-form-item__content {
display: flex;
gap: 16px;
flex-wrap: wrap;
&:before {
content: none;
}
.el-image__inner {
width: 82px;
height: 82px;
}
}
}
}
</style>

View File

@@ -9,24 +9,24 @@
<ai-search-bar>
<template #left>
<ai-select
v-model="search.eventStatus"
clearable
placeholder="处理状态"
:selectList="dict.getDict('clapEventStatus')"
@change="search.current = 1, getList()">
v-model="search.eventStatus"
clearable
placeholder="处理状态"
:selectList="dict.getDict('clapEventStatus')"
@change="search.current = 1, getList()">
</ai-select>
</template>
<template #right>
<el-input
v-model="search.content"
class="search-input"
size="small"
v-throttle="() => {search.current = 1, getList()}"
placeholder="请输入内容描述/上报居民/联系方式"
clearable
@change="getList"
@clear="search.current = 1, search.content = '', getList()"
suffix-icon="iconfont iconSearch">
v-model="search.content"
class="search-input"
size="small"
v-throttle="() => {search.current = 1, getList()}"
placeholder="请输入内容描述/上报居民/联系方式"
clearable
@change="getList"
@clear="search.current = 1, search.content = '', getList()"
suffix-icon="iconfont iconSearch">
</el-input>
</template>
</ai-search-bar>
@@ -34,6 +34,7 @@
<el-table-column slot="options" label="操作" fixed="right" width="120" align="center">
<div class="table-options" slot-scope="{row}">
<el-button type="text" title="详情" @click="toDetail(row.id)">详情</el-button>
<el-button type="text" title="删除" @click="handleDelete(row.id)">删除</el-button>
</div>
</el-table-column>
</ai-table>
@@ -42,94 +43,106 @@
</template>
<script>
import { mapState } from 'vuex'
import {mapState} from 'vuex'
export default {
name: 'List',
label: "随手拍",
export default {
name: 'List',
label: "随手拍",
props: {
instance: Function,
dict: Object
},
props: {
instance: Function,
dict: Object
},
data() {
return {
userList: [],
search: {
current: 1,
size: 10,
eventStatus: '',
content: ''
},
total: 0,
tableData: [],
content: '',
id: ''
}
},
computed: {
...mapState(['user']),
colConfigs() {
return [
{ prop: 'content', label: '内容描述', width: '300px' },
{ prop: 'groupName', label: '事件类型', align: 'center' },
{ prop: 'girdName', label: '所属网格', align: 'center' },
{ prop: 'createTime', label: '上报时间', align: 'center' },
{ prop: 'name', label: '上报居民', align: 'center' },
{ prop: 'phone', label: '联系方式', align: 'center' },
{ prop: 'eventStatus', label: '处理状态', align: 'center', formart: v => this.dict.getLabel('clapEventStatus', v) },
{ prop: 'processTime', label: '处理时长', align: 'center' },
{ slot: 'options' }
]
data() {
return {
userList: [],
search: {
current: 1,
size: 10,
eventStatus: '',
content: ''
},
total: 0,
tableData: [],
content: '',
id: ''
}
},
handleStatusOps() {
return this.dict.getDict("reportAtWillHandleStatus").map(e => ({label: e.dictName, value: e.dictValue}))
}
computed: {
...mapState(['user']),
colConfigs() {
return [
{prop: 'content', label: '内容描述', width: '300px'},
{prop: 'groupName', label: '事件类型', align: 'center'},
{prop: 'girdName', label: '所属网格', align: 'center'},
{prop: 'createTime', label: '上报时间', align: 'center'},
{prop: 'name', label: '上报居民', align: 'center'},
{prop: 'phone', label: '联系方式', align: 'center'},
{prop: 'eventStatus', label: '处理状态', align: 'center', formart: v => this.dict.getLabel('clapEventStatus', v)},
{prop: 'processTime', label: '处理时长', align: 'center'},
{slot: 'options'}
]
},
created () {
this.dict.load('clapEventStatus').then(() => {
this.getList()
handleStatusOps() {
return this.dict.getDict("reportAtWillHandleStatus").map(e => ({label: e.dictName, value: e.dictValue}))
}
},
created() {
this.dict.load('clapEventStatus').then(() => {
this.getList()
})
},
methods: {
getList() {
this.instance.post(`/app/appclapeventinfo/list`, null, {
params: {
...this.search
}
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
},
methods: {
getList () {
this.instance.post(`/app/appclapeventinfo/list`, null, {
params: {
...this.search
}
toDetail(id) {
this.$emit('change', {
type: 'Detail',
params: {
id: id || ''
}
})
},
toSetting() {
this.$emit('change', {
type: 'Setting',
params: {
id: ''
}
})
},
handleDelete(ids) {
this.$confirm("是否要进行删除?").then(() => {
this.instance.post("/app/appclapeventinfo/delete", null, {
params: {ids}
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
if (res?.code == 0) {
this.$message.success("删除成功!")
this.getList()
}
})
},
toDetail (id) {
this.$emit('change', {
type: 'Detail',
params: {
id: id || ''
}
})
},
toSetting () {
this.$emit('change', {
type: 'Setting',
params: {
id: ''
}
})
}
}).catch(() => 0)
}
}
}
</script>
<style lang="scss" scoped>

View File

@@ -0,0 +1,239 @@
<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.description" isLine></ai-info-item>
<ai-info-item label="联系电话" isLine :value="info.residentPhone"></ai-info-item>
<ai-info-item label="图片" isLine>
<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' ? '通过' : '拒绝'" isLine></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-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-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 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>
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="isShow = true" v-if="info.auditStatus === '0'">审核</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: false,
form: {
auditIntegralType: '',
auditRuleId: '',
opinion: '',
pass: ''
},
ruleList: []
}
},
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() {
if (this.params && this.params.id) {
this.id = this.params.id
this.dict.load(['atWillReportType', 'auditStatus']).then(() => {
this.getInfo(this.params.id)
})
}
},
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>

View File

@@ -0,0 +1,76 @@
<template>
<ai-list>
<template slot="title">
<ai-title title="积分维护" :isShowBottomBorder="false" :instance="instance" :isShowArea="true" v-model="areaId"
@change="changeArea"></ai-title>
</template>
<template slot="tabs">
<el-tabs v-model="currIndex">
<el-tab-pane v-for="(tab,i) in tabs" :key="i" :label="tab.label">
<component :is="tab.comp" v-if="currIndex === String(i)" :ref="tab.name"
:areaId="areaId" :instance="instance" :dict="dict" :permissions="permissions"/>
</el-tab-pane>
</el-tabs>
</template>
</ai-list>
</template>
<script>
import pointsDeclaration from "./pointsDeclaration.vue"
import pointsDetails from "./pointsDetails.vue"
import pointsAppeal from './pointsAppeal'
import {mapState} from 'vuex'
import scoreChange from "./scoreChange";
export default {
name: 'AppScoreManage',
label: "积分维护",
components: {pointsDeclaration, pointsDetails, pointsAppeal, scoreChange},
props: {
instance: Function,
dict: Object,
permissions: Function
},
computed: {
...mapState(['user']),
tabs() {
return [
{
label: "积分明细",
name: "pointsDetails",
comp: pointsDetails,
permission: "app_apppartyfee_statistics",
},
{
label: "积分调整",
name: "scoreChange",
comp: scoreChange,
permission: "",
},
]
}
},
created() {
this.areaId = this.user.info.areaId
this.dict.load("integralCalcType")
},
methods: {
changeArea() {
this.$nextTick(() => {
this.$refs[this.tabs[Number(this.currIndex)].name][0].getList()
})
}
},
data() {
return {
activeName: "pointsDeclaration",
currIndex: '0',
areaId: ''
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,219 @@
<template>
<section class="pointsDetails">
<ai-list isTabs>
<template slot="content">
<ai-search-bar bottomBorder>
<template slot="left">
<el-date-picker size="small" v-model="searchDotime" type="daterange" range-separator="至" @change="timeChange"
start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd HH:mm:ss" format="yyyy-MM-dd"></el-date-picker>
</template>
<template slot="right">
<el-input
v-model="search.familyName"
class="search-input"
size="small"
placeholder="对象、户主、事件类型"
clearable
v-throttle="() => {search.current = 1, getList()}"
@clear="search.current = 1, getList()"
suffix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total" :dict="dict"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList">
<el-table-column slot="changeIntegral" label="积分" align="center">
<template slot-scope="{ row }">
<span>{{ row.integralCalcType == 1 ? '+' : '-' }}{{ row.changeIntegral }}</span>
</template>
</el-table-column>
<el-table-column slot="options" label="操作" align="center" fixed="right" width="120">
<template slot-scope="{ row }">
<el-button
type="text"
title="详情"
:disabled="!$permissions('app_appvillagerintegraldetail_detail')"
@click="viewItem(row)">
详情
</el-button>
</template>
</el-table-column>
</ai-table>
</template>
</ai-list>
<ai-dialog title="详情" :visible.sync="dialog" :customFooter="true" :destroyOnClose="true" width="720px">
<ai-wrapper>
<ai-info-item label="户主:" :value="dialogInfo.familyName"/>
<ai-info-item label="对象:" :value="dialogInfo.residentName"/>
<ai-info-item label="事件:" :value="dialogInfo.eventDesc" isLine/>
<ai-info-item label="时间:" :value="dialogInfo.doTime" isLine/>
<ai-info-item label="积分:">
{{ dialogInfo.changeIntegral >= 0 ? '增加' : '减少' }}
<span style="color:#26f" v-text="Math.abs(dialogInfo.changeIntegral)"/>
</ai-info-item>
<ai-info-item label="积分余额:" :value="dialogInfo.nowIntegral"/>
</ai-wrapper>
<div class="dialog-footer" slot="footer">
<el-button @click="dialog=false">关闭</el-button>
</div>
</ai-dialog>
</section>
</template>
<script>
export default {
name: "pointsDeclaration",
props: {
instance: Function,
dict: Object,
areaId: String
},
data() {
return {
searchDotime: [],
search: {
current: 1,
size: 10,
familyName: '',
doTimeStart: null,
doTimeEnd: null
},
total: 10,
colConfigs: [
{prop: "residentName", label: "对象", width: 160},
{prop: "familyName", label: "户主", align: "center", width: 160},
{prop: "eventDesc", label: "事件", "show-overflow-tooltip": true, width: 420},
{prop: "doTime", label: "时间", width: 200},
{prop: "type", label: "类型", width: 100, dict: "integralDetailType"},
{slot: "changeIntegral", label: "积分", width: 100},
{slot: "options", label: "操作", align: "center"},
],
tableData: [],
dialog: false,
dialogInfo: {},
};
},
mounted() {
this.$dict
.load([
"integralDeclareDoType",
"integralDetailType",
])
.then(() => {
this.getList();
});
},
methods: {
getList() {
this.instance.post(`/app/appvillagerintegraldetail/list`, null, {
params: {
...this.search,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.tableData = res.data.records;
this.total = res.data.total;
}
});
},
timeChange() {
if (this.searchDotime) {
this.search.doTimeStart = this.searchDotime[0]
this.search.doTimeEnd = this.searchDotime[1]
} else {
this.search.doTimeStart = null
this.search.doTimeEnd = null
}
this.search.current = 1
this.getList()
},
viewItem(row) {
this.dialog = true
this.instance.post(`/app/appvillagerintegraldetail/queryDetailById?id=${row.id}`, null, {}).then((res) => {
if (res?.data) {
this.dialogInfo = res.data
}
});
},
onReset() {
this.search.current = 1
this.search.doTimeStart = null
this.search.doTimeEnd = null
this.search.familyName = ''
this.searchDotime = []
this.getList();
},
},
};
</script>
<style lang="scss">
.pointsDetails {
height: 100%;
background: #f3f6f9;
overflow: auto;
.form_content {
.form_flex {
display: flex;
div {
flex: 1;
}
}
.form_info {
margin-bottom: 8px;
}
.form_label {
display: inline-block;
color: #999;
vertical-align: top;
width: 70px;
text-align: right;
}
.form_value {
display: inline-block;
color: #333;
width: calc(100% - 70px);
// img {
// width: 100px;
// height: 100px;
// margin: 0 8px 8px 0;
// }
}
}
.form_div {
padding-top: 24px;
border-top: 1px solid #eee;
}
.status-0 {
color: #FF4466;
}
.status-1 {
color: #2EA222;
}
.status-2 {
color: #999999;
}
}
</style>

View File

@@ -14,7 +14,7 @@
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
:total="page.total" :dict="dict"
:current.sync="page.current"
:size.sync="page.size"
@getList="getList">
@@ -39,18 +39,15 @@
</template>
</ai-person-select>
</el-form-item>
<el-form-item label="调整说明" prop="description">
<el-input v-model.trim="form.description" placeholder="请输入..." type="textarea" :rows="4" show-word-limit
<el-form-item label="调整说明" prop="eventDesc">
<el-input v-model.trim="form.eventDesc" placeholder="请输入..." type="textarea" :rows="4" show-word-limit
maxlength="100"></el-input>
</el-form-item>
<el-form-item label="类型" prop="doType">
<el-radio-group v-model="form.doType">
<el-radio label="0">加分</el-radio>
<el-radio label="1">减分</el-radio>
</el-radio-group>
<el-form-item label="类型" prop="integralCalcType">
<ai-select v-model="form.integralCalcType" :selectList="dict.getDict('integralCalcType')"/>
</el-form-item>
<el-form-item label="积分" prop="changeIntegral">
<el-input v-model.trim.num="form.changeIntegral" placeholder="请输入正数" size="small"></el-input>
<el-input v-model.trim.num="form.changeIntegral" placeholder="请输入正数" size="small"></el-input>
</el-form-item>
</el-form>
</ai-dialog>
@@ -86,38 +83,19 @@ export default {
rules() {
return {
residentId: [{required: true, message: '请选择人员', trigger: 'blur'},],
description: [{required: true, message: '请输入调整说明', trigger: 'blur'},],
doType: [{required: true, message: '请输入调整说明', trigger: 'change'},],
changeIntegral: [
{
required: true, validator: (rule, value, callback) => {
if (!/^[1-9]\d*$/.test(value)) {
callback(new Error('请输入正整数'))
} else {
callback();
}
}, trigger: 'blur'
},],
eventDesc: [{required: true, message: '请输入调整说明', trigger: 'blur'},],
integralCalcType: [{required: true, message: '请选择类型', trigger: 'change'},],
changeIntegral: [{required: true, validator: (r, v, cb) => v > 0 ? cb() : cb("请输入正数")}],
}
},
colConfigs() {
return [
{prop: "residentName", label: "姓名"},
{prop: "description", label: "调整说明"},
{
prop: "changeIntegral", label: "类型", align: "center",
render: (h, {row}) => [< span> {+row.changeIntegral > 0 ? "加分" : '减分'
} < /span>]
},
{
prop: "changeIntegral",
label: "积分",
align: "center",
render: (h, {row}) => [
<span>{row.changeIntegral > 0 ? `+${row.changeIntegral}` : `${row.changeIntegral}`}</span>]
},
{prop: "eventDesc", label: "调整说明"},
{prop: "integralCalcType", label: "类型", dict: "integralCalcType", align: 'center'},
{prop: "changeIntegral", label: "积分", align: "center", render: (h, {row}) => h('p',{textAlign:'center'}, `${row.integralCalcType > 0 ? '+' : '-'}${row.changeIntegral}`)},
{prop: "doTime", label: "操作时间"},
{prop: "declareObjName", label: "操作人", align: "center"},
{prop: "createUserName", label: "操作人", align: "center"},
]
}
},
@@ -134,10 +112,7 @@ export default {
onConfirm() {
this.$refs['form'].validate(valid => {
if (valid) {
this.instance.post(`/app/appvillagerintegraldetail/changeIntegral`, {
...this.form,
changeIntegral: this.form.doType == 0 ? `+${this.form.changeIntegral}` : `-${this.form.changeIntegral}`
}).then(res => {
this.instance.post(`/app/appvillagerintegraldetail/changeIntegral`, this.form).then(res => {
if (res.code == 0) {
this.$message.success("添加成功")
this.dialog = false
@@ -149,11 +124,7 @@ export default {
},
getList() {
this.instance.post(`/app/appvillagerintegraldetail/list`, null, {
params: {
...this.page,
areaId: this.areaId,
doType: 2
}
params: {...this.page, areaId: this.areaId, type: 0}
}).then(res => {
if (res?.data) {
this.tableData = res.data.records

View File

@@ -43,7 +43,6 @@
<el-table-column label="操作" slot="options" fixed="right" align="center" width="180">
<template v-slot="{row}">
<div class="table-options">
<!-- <el-button type="text" title="编辑" @click="edit(row)" :disabled="!$permissions('app_appvillagerintegralfamily_edit')">编辑</el-button> -->
<el-button type="text" title="家庭成员" @click="familyMember(row)" :disabled="!$permissions('app_appvillagerintegralfamilymember_edit')">家庭成员</el-button>
<el-button type="text" :disabled="!$permissions('app_appvillagerintegralfamily_detail')" title="详情" @click="goDetail(row)">详情</el-button>
</div>
@@ -53,93 +52,12 @@
</template>
</ai-list>
<detail v-if="detailShow" @goBack="goBack" :detailInfo='detailInfo' :instance='instance' :dict='dict'></detail>
<ai-dialog
:title="dialog.title"
:visible.sync="dialog.visible"
:customFooter="true"
:destroyOnClose="true"
@close="init('ruleForm')"
width="520px">
<div class="form_div">
<el-form ref="ruleForm" :model="dialogInfo" :rules="formRules" size="small" label-suffix=""
label-width="120px">
<el-form-item label="类型" prop="personType">
<el-radio-group v-model="dialogInfo.personType" @change="typeChange"
:disabled="dialog.title.indexOf('修改')!=-1">
<el-radio label="0">户籍居民</el-radio>
<el-radio label="1">外来人员</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="dialog.title.indexOf('家庭')!=-1?'户主':'姓名'" prop="name">
<el-row type="flex" :gutter="8">
<el-col>
<el-input v-model="dialogInfo.name" disabled clearable/>
</el-col>
<el-col>
<ai-person-select :instance="instance" :key="personUrl" :url="personUrl" @selectPerson="getSelect"
v-if="dialog.title.indexOf('添加')!=-1"></ai-person-select>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="身份证号" prop="idNumber">
<el-input v-model="dialogInfo.idNumber" disabled clearable/>
</el-form-item>
<el-form-item label="联系电话" prop="phone">
<el-input type="number" v-model="dialogInfo.phone" maxlength="11" clearable/>
</el-form-item>
<el-form-item label="所属组" prop="villageGroup" v-if="dialog.title.indexOf('家庭')!=-1">
<el-select v-model="dialogInfo.villageGroup" placeholder="请选择...">
<el-option
v-for="(item,i) in dict.getDict('integralVillageGroup')"
:key="i"
:label="item.dictName"
:value="item.dictValue"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status" v-if="dialog.title.indexOf('家庭')!=-1">
<el-select v-model="dialogInfo.status" placeholder="请选择...">
<el-option
v-for="(item,i) in dict.getDict('integralRuleStatus')"
:key="i"
:label="item.dictName"
:value="item.dictValue"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="与户主关系" prop="householdRelation" v-if="dialog.title.indexOf('成员')!=-1">
<el-select
v-model="dialogInfo.householdRelation"
placeholder="请选择"
size="mini"
clearable
style="width:216px;"
>
<el-option
v-for="(item,i) in dict.getDict('householdRelation')"
:label="item.dictName"
:key="i"
:value="item.dictValue"
></el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer" slot="footer">
<el-button @click="dialog.visible=false" size="medium">取消</el-button>
<el-button @click="onConfirm('ruleForm')" type="primary" size="medium">确认</el-button>
</div>
</ai-dialog>
<ai-dialog class="family-list"
title="成员列表"
:visible.sync="addMemberVisible"
:customFooter="true"
:destroyOnClose="true"
width="780px">
<!-- <p class="add_btn">
<span class="iconfont iconAdd" @click="addFamily()"></span>
<span @click="addFamily()">添加家庭成员</span>
</p> -->
<ai-table
:tableData="familyList"
:col-configs="familycolConfigs"
@@ -162,16 +80,6 @@
<ai-id mode="show" :show-eyes="false" :value="row.idNumber"/>
</template>
</el-table-column>
<!-- <el-table-column label="操作" slot="options" align="center">
<template v-slot="{row}">
<el-button type="text"
v-if="row.householdRelation!=11&&$permissions('app_appvillagerintegralfamilymember_edit')"
icon="iconfont iconEdit" title="编辑" @click="editFamily(row)"/>
<el-button type="text"
v-if="row.householdRelation!=11&&$permissions('app_appvillagerintegralfamilymember_del')"
icon="iconfont iconDelete" title="删除" @click="deleteFamily(row.id)"/>
</template>
</el-table-column> -->
</ai-table>
<div class="dialog-footer" slot="footer">
<el-button @click="addMemberVisible=false" size="medium"> </el-button>
@@ -334,45 +242,10 @@ export default {
]
},
formRules() {
let IdNumberPass = (rule, value, callback) => {
if (value) {
console.log(this.idCardNoUtil);
if (this.idCardNoUtil.checkIdCardNo(value)) {
callback();
} else {
callback(new Error("身份证号格式错误"));
}
} else {
callback(new Error("请输入身份证号"));
}
};
if (this.dialog.title.indexOf('家庭') != -1) {
return {
personType: [{required: true, message: "请选择类型", trigger: 'change'}],
name: [{required: true, message: "请填写户主", trigger: 'change'}],
idNumber: [{required: true, validator: IdNumberPass, trigger: 'change'}],
phone: [{required: true, message: "请填写联系电话", trigger: 'blur'}],
villageGroup: [{required: true, message: "请选择所属组", trigger: 'change'}],
status: [{required: true, message: "请选择状态", trigger: 'change'}],
householdRelation: [{required: true, message: "请选择与户主关系", trigger: 'change'}]
}
} else {
return {
personType: [{required: true, message: "请选择类型", trigger: 'change'}],
name: [{required: true, message: "请填写户主", trigger: 'change'}],
idNumber: [{required: true, validator: IdNumberPass, trigger: 'change'}],
villageGroup: [{required: true, message: "请选择所属组", trigger: 'change'}],
status: [{required: true, message: "请选择状态", trigger: 'change'}],
householdRelation: [{required: true, message: "请选择与户主关系", trigger: 'change'}]
}
}
}
},
created() {
this.areaId = this.user.info.areaId;
this.dict.load('integralVillageGroup', 'integralRuleStatus', 'integralPersonType', 'householdRelation', 'residentType');
this.dict.load('integralVillageGroup', 'integralRuleStatus', 'householdRelation', 'residentType');
this.getList();
},
methods: {
@@ -390,124 +263,6 @@ export default {
}
})
},
typeChange(val) {
val == '0' ? this.personUrl = '/app/appresident/list?fileStatus=0' : this.personUrl = '/app/apprecurrentpopulation/list?fileStatus=0';
this.dialogInfo.name = "";
this.dialogInfo.idNumber = "";
this.dialogInfo.phone = "";
this.dialogInfo.avatar = "";
this.dialogInfo.areaId = "";
},
add() {
this.dialog.visible = true;
this.dialog.title = '添加家庭';
},
addFamily() {
this.dialog.visible = true;
this.dialog.title = '添加成员';
},
onConfirm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
if (this.dialog.title.indexOf('家庭') != -1) {
this.instance.post("/app/appvillagerintegralfamily/addOrUpdate", {
...this.dialogInfo,
}, null).then(res => {
if (res.code == 0) {
this.dialog.visible = false;
if (this.dialog.title.indexOf('添加') != -1) {
this.$message.success("添加成功")
} else {
this.$message.success("修改成功")
}
this.getList();
}
})
} else {
this.instance.post("/app/appvillagerintegralfamilymember/addOrUpdate", {
...this.dialogInfo,
familyId: this.familyId,
familyIdNumber: this.rowInfo.idNumber,
familyName: this.rowInfo.name
}, null).then(res => {
if (res.code == 0) {
this.dialog.visible = false;
if (this.dialog.title.indexOf('添加') != -1) {
this.$message.success("添加成功")
} else {
this.$message.success("修改成功")
}
this.familyMember(this.rowInfo);
this.getList();
}
})
}
} else {
return false;
}
});
},
init(formName) {
this.$refs[formName].clearValidate();
Object.keys(this.dialogInfo).forEach(e => {
this.dialogInfo[e] = ''
})
this.dialogInfo.personType = '0';
this.personUrl = '';
},
reset() {
Object.keys(this.searchObj).forEach(e => {
this.searchObj[e] = ''
});
this.getList();
},
edit(row) {
this.dialog.visible = true;
this.dialog.title = '修改家庭';
this.dialogInfo = {...row}
},
editFamily(row) {
this.dialog.visible = true;
this.dialog.title = '修改成员';
this.dialogInfo = {...row}
},
deleteFamily(ids) {
ids && this.$confirm("是否要删除该家庭成员", {
type: 'error'
}).then(() => {
this.instance.post("/app/appvillagerintegralfamilymember/delete", null, {
params: {ids}
}).then(res => {
if (res?.code == 0) {
this.$message.success("删除成功!")
this.familyMember(this.rowInfo);
}
})
}).catch(() => {
})
},
getSelect(val) {
console.log(val)
if (val) {
this.dialogInfo.name = val.name;
this.dialogInfo.idNumber = val.idNumber;
this.dialogInfo.avatar = val.photo;
if (this.dialogInfo.personType == 0) {
this.dialogInfo.areaId = val.householdAreaId;
} else {
this.dialogInfo.areaId = val.currentAreaId;
}
} else {
this.dialogInfo.name = '';
this.dialogInfo.idNumber = '';
this.dialogInfo.phone = '';
this.dialogInfo.areaId = '';
this.dialogInfo.avatar = '';
this.$refs['rules'].clearValidate();
}
},
familyMember(row) {
this.rowInfo = {...row}
this.familyId = row.id;

View File

@@ -28,31 +28,20 @@
:instance="instance"
url="/app/appvillagerintegraldetail/export"
:disabled="!Boolean(tableData.length)"
:params="{familyId:detailInfo.id,bizType:doType}"
:params="{familyId:detailInfo.id,type}"
fileName="余额变动明细">
<span class="iconfont iconExported">导出</span>
<el-button type="text" icon="iconfont iconExported">导出</el-button>
</ai-download>
</template>
<template #content>
<el-select v-model="doType" placeholder="请选择类型" size='small' clearable @change="page.current=1,getList()">
<el-option
v-for="(item,i) in dict.getDict('integralDetailType')"
:label="item.dictName"
:key="i"
:value="item.dictValue">
</el-option>
</el-select>
<ai-table
style="margin-top: 16px;"
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
:border="true"
:stripe="false"
:current.sync="page.current"
:size.sync="page.size"
@getList="getList">
</ai-table>
<ai-search-bar>
<template #left>
<ai-select v-model="type" placeholder="请选择类型" @change="page.current=1,getList()"
:selectList="dict.getDict('integralDetailType')"/>
</template>
</ai-search-bar>
<ai-table :tableData="tableData" :col-configs="colConfigs"
:total="page.total" border :dict="dict" :current.sync="page.current" :size.sync="page.size" @getList="getList"/>
</template>
</ai-card>
</template>
@@ -62,7 +51,6 @@
<script>
export default {
name: 'balance',
props: {
detailInfo: {
type: Object,
@@ -79,61 +67,31 @@ export default {
size: 10,
total: 0
},
doType: '',
type: "",
tableData: []
}
},
created() {
this.dict.load('integralDetailType')
this.getList()
},
computed: {
colConfigs() {
const _this = this
return [
{
prop: 'doTime',
label: '时间'
},
{
prop: 'bizType',
align: 'center',
label: '类型',
render(h, {row}) {
return h('span', {}, _this.dict.getLabel('integralDetailType', row.bizType))
}
},
{
prop: 'changeIntegral',
align: 'center',
label: '变动积分',
formart: v => v > 0 ? `+${v}` : v
},
{
prop: 'nowIntegral',
align: 'center',
label: '剩余积分'
},
{
prop: 'description',
label: '事件类型',
}
{prop: 'doTime', label: '时间', width: 200},
{prop: "type", label: "类型", dict: "integralDetailType", align: 'center'},
{prop: 'changeIntegral', align: 'center', label: '变动积分', render: (h, {row}) => h('p', `${row.integralCalcType == 1 ? '+' : '-'}${row.changeIntegral}`)},
{prop: 'nowIntegral', align: 'center', label: '剩余积分'},
{prop: 'eventDesc', label: '事件', width: 500}
]
}
},
methods: {
getList() {
this.instance.post('/app/appvillagerintegraldetail/list', null, {
params: {
...this.page,
familyId: this.detailInfo.id,
bizType: this.doType
}
params: {...this.page, familyId: this.detailInfo.id, type: this.type}
}).then(res => {
if (res.code === 0) {
if (res?.data) {
this.tableData = res.data.records
this.page.total = res.data.total
}
@@ -148,11 +106,6 @@ export default {
height: 100%;
background-color: #fff;
::v-deep .ai-card__body {
padding: 12px 16px 20px !important;
}
.detail-info {
display: flex;
align-items: center;
@@ -187,25 +140,5 @@ export default {
}
}
}
.iconExported {
color: #5088FF;
font-size: 12px;
cursor: pointer;
}
.info {
padding: 16px 0 16px 0;
}
.do_type {
height: 56px;
}
.fs-14 {
::v-deep .el-table--small {
font-size: 14px !important;
}
}
}
</style>

View File

@@ -1,84 +0,0 @@
<template>
<ai-list>
<template slot="title">
<ai-title title="积分管理" :isShowBottomBorder="false" :instance="instance" :isShowArea="true" v-model="areaId"
@change="changeArea"></ai-title>
</template>
<template slot="tabs">
<el-tabs v-model="currIndex">
<el-tab-pane v-for="(tab,i) in tabs" :key="i" :label="tab.label">
<component :is="tab.comp" v-if="currIndex === String(i)" :bizType="tab.bizType" :ref="tab.name"
:areaId="areaId" :instance="instance" :dict="dict" :permissions="permissions"/>
</el-tab-pane>
</el-tabs>
</template>
</ai-list>
</template>
<script>
import pointsDeclaration from "./pointsDeclaration.vue"
import pointsDetails from "./pointsDetails.vue"
import pointsAppeal from './pointsAppeal'
import {mapState} from 'vuex'
import scoreChange from "./scoreChange";
export default {
name: 'AppScoreManage',
label: "积分管理",
components: {pointsDeclaration, pointsDetails, pointsAppeal, scoreChange},
props: {
instance: Function,
dict: Object,
permissions: Function
},
computed: {
...mapState(['user']),
tabs() {
return [
// {
// label: "积分申报",
// name: "pointsDeclaration",
// comp: pointsDeclaration,
// permission: "app_apppartyfee_record",
// bizType: '0'
// },
// { label: "积分申诉", name: "pointsAppeal", comp: pointsAppeal, permission: "app_apppartyfee_config", bizType: '1'},
{
label: "积分明细",
name: "pointsDetails",
comp: pointsDetails,
permission: "app_apppartyfee_statistics",
bizType: '2'
},
{
label: "积分调整",
name: "scoreChange",
comp: scoreChange,
permission: "",
},
]
}
},
created() {
this.areaId = this.user.info.areaId
},
methods: {
changeArea() {
this.$nextTick(() => {
this.$refs[this.tabs[Number(this.currIndex)].name][0].getList()
})
}
},
data() {
return {
activeName: "pointsDeclaration",
currIndex: '0',
areaId: ''
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -1,283 +0,0 @@
<template>
<section class="pointsDetails">
<ai-list isTabs>
<template slot="content">
<ai-search-bar bottomBorder>
<template slot="left">
<el-date-picker size="small" v-model="searchDotime" type="daterange" range-separator="至" @change="timeChange"
start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd HH:mm:ss" format="yyyy-MM-dd"></el-date-picker>
</template>
<template slot="right">
<el-input
v-model="search.familyName"
class="search-input"
size="small"
placeholder="对象、户主、事件类型"
clearable
v-throttle="() => {search.current = 1, getList()}"
@clear="search.current = 1, getList()"
suffix-icon="iconfont iconSearch" />
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
ref="aitableex"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList">
<el-table-column slot="changeIntegral" label="积分" align= "center">
<template slot-scope="{ row }">
<span>{{row.changeIntegral > 0 ? '+' : ''}}{{row.changeIntegral}}</span>
</template>
</el-table-column>
<el-table-column slot="doType" label="类型" align= "center">
<template slot-scope="{ row }">
<span>{{ dict.getLabel('integralDetailType', row.bizType) }}</span>
</template>
</el-table-column>
<el-table-column slot="options" label="操作" align="center" fixed="right" width="120">
<template slot-scope="{ row }">
<el-button
type="text"
title="详情"
:disabled="!$permissions('app_appvillagerintegraldetail_detail')"
@click="viewItem(row)">
详情
</el-button>
</template>
</el-table-column>
</ai-table>
</template>
</ai-list>
<ai-dialog
title="详情"
:visible.sync="dialog.visible"
:customFooter="true"
:destroyOnClose="true"
width="720px"
>
<div class="form_content">
<div class="form_info">
<span class="form_label">户主</span>
<span class="form_value">{{dialogInfo.familyName}}</span>
</div>
<div class="form_info">
<span class="form_label">事项</span>
<span class="form_value">{{dialogInfo.ruleName}}</span>
</div>
<div class="form_flex form_info">
<div>
<span class="form_label">积分</span>
<span class="form_value">{{dialogInfo.changeIntegral >= 0 ? '增加' : '减少'}}<span style="color:#2266FF">{{Math.abs(dialogInfo.changeIntegral)}}</span></span>
</div>
<!-- <div>
<span class="form_label">途径</span>
<span class="form_value">{{$dict.getLabel("integralDetailBizType", dialogInfo.bizType)}}</span>
</div> -->
</div>
<!-- <div class="form_info">
<span class="form_label">{{dialogInfo.bizType == 1 ? '申诉' : '申报'}}说明</span>
<span
class="form_value"
>{{dialogInfo.description}}</span>
</div>
<div class="form_info">
<span class="form_label">照片</span>
<span class="form_value" v-if="dialogInfo.fileList && dialogInfo.fileList.length">
<ai-uploader :disabled="true" :instance="instance" v-model="dialogInfo.fileList" :limit="9" ></ai-uploader>
</span>
<span class="form_value" v-else>-</span>
</div> -->
</div>
<div class="dialog-footer" slot="footer">
<el-button @click="dialog.visible=false" size="medium">关闭</el-button>
</div>
</ai-dialog>
</section>
</template>
<script>
export default {
name: "pointsDeclaration",
props: {
instance: Function,
dict: Object,
areaId:String
},
data() {
return {
searchDotime: [],
search: {
current: 1,
size: 10,
familyName: '',
doTimeStart: null,
doTimeEnd: null
},
total: 10,
colConfigs: [
{ prop: "residentName", label: "对象", width:160 },
{ prop: "familyName", label: "户主", align: "center", width:160 },
{
prop: "ruleName",
label: "事件类型",
"show-overflow-tooltip": true,
width:420
},
{
prop: "doTime",
label: "时间",
width:200
},
// {
// prop: "doType",
// label: "类型",
// align: "center",
// width: 100,
// render: (h, params) => {
// return h(
// "span",
// {
// class: "status-" + params.row.doType,
// },
// this.$dict.getLabel("integralIntegralType", params.row.doType)
// );
// },
// },
{ slot: "doType", label: "类型", width: 100},
{ slot: "changeIntegral", label: "积分", width: 100},
// {
// prop: "bizType",
// label: "途径",
// align: "center",
// width: 100,
// formart: (bizType) =>
// this.$dict.getLabel("integralDetailBizType", bizType) || '-',
// },
{ slot: "options", label: "操作", align: "center" },
],
tableData: [],
dialog: {
visible: false,
},
dialogInfo: {},
};
},
mounted() {
this.$dict
.load([
"integralDeclareDoType",
"integralDetailType",
"integralDetailBizType"
])
.then(() => {
this.getList();
});
},
methods: {
getList() {
this.instance
.post(`/app/appvillagerintegraldetail/list`, null, {
params: {
...this.search,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.tableData = res.data.records;
this.total = res.data.total;
}
});
},
timeChange() {
if(this.searchDotime) {
this.search.doTimeStart = this.searchDotime[0]
this.search.doTimeEnd = this.searchDotime[1]
}else {
this.search.doTimeStart = null
this.search.doTimeEnd = null
}
this.search.current = 1
this.getList()
},
viewItem(row) {
this.dialog.visible = true
this.instance.post(`/app/appvillagerintegraldetail/queryDetailById?id=${row.id}`, null, {}).then((res) => {
if (res.code == 0) {
this.dialogInfo = res.data
console.log(this.dialogInfo)
}
});
},
onReset() {
this.search.current = 1
this.search.doTimeStart = null
this.search.doTimeEnd = null
this.search.familyName = ''
this.searchDotime = []
this.getList();
},
},
};
</script>
<style lang="scss">
.pointsDetails {
height: 100%;
background: #f3f6f9;
overflow: auto;
.form_content {
.form_flex {
display: flex;
div {
flex: 1;
}
}
.form_info {
margin-bottom: 8px;
}
.form_label {
display: inline-block;
color: #999;
vertical-align: top;
width: 70px;
text-align: right;
}
.form_value {
display: inline-block;
color: #333;
width: calc(100% - 70px);
// img {
// width: 100px;
// height: 100px;
// margin: 0 8px 8px 0;
// }
}
}
.form_div {
padding-top: 24px;
border-top: 1px solid #eee;
}
.status-0 {
color: #FF4466;
}
.status-1 {
color: #2EA222;
}
.status-2 {
color: #999999;
}
}
</style>

View File

@@ -1,171 +0,0 @@
<template>
<div class="scoreChange">
<ai-list isTabs>
<template slot="content">
<ai-search-bar bottomBorder>
<template slot="left">
<el-button type="primary" icon="iconfont iconAdd" @click="dialog=true"
:disabled="!permissions('app_appvillagerintegraldetail_change')">添加
</el-button>
<ai-import :instance="instance" :dict="dict" name="积分调整" type="appvillagerintegraldetail"
v-if="permissions('app_appvillagerintegraldetail_change')" @success="getList"/>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
:current.sync="page.current"
:size.sync="page.size"
@getList="getList">
</ai-table>
</template>
</ai-list>
<ai-dialog
title="添加积分调整"
:visible.sync="dialog"
:destroyOnClose="true"
width="720px"
@onConfirm="onConfirm"
@closed="form={}">
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="选择人员" prop="residentId">
<ai-person-select :instance="instance" :customClicker="true"
:url="'/app/appresident/list?auditType=1areaId=' + user.info.areaId"
:isMultiple="false" dialogTitle="选择" @selectPerson="selectPerson">
<template name="option" v-slot:option="{ item }">
<span class="iconfont iconProlife">{{ item.name }}</span>
<ai-id mode="show" :show-eyes="false" :value="item.idNumber"/>
</template>
</ai-person-select>
</el-form-item>
<el-form-item label="调整说明" prop="description">
<el-input v-model.trim="form.description" placeholder="请输入..." type="textarea" :rows="4" show-word-limit
maxlength="100"></el-input>
</el-form-item>
<el-form-item label="类型" prop="doType">
<el-radio-group v-model="form.doType">
<el-radio label="0">加分</el-radio>
<el-radio label="1">减分</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="积分" prop="changeIntegral">
<el-input v-model.trim.num="form.changeIntegral" placeholder="请输入正整数" size="small"></el-input>
</el-form-item>
</el-form>
</ai-dialog>
</div>
</template>
<script>
import {mapState} from "vuex"
export default {
name: "scoreChange",
props: {
instance: Function,
dict: Object,
permissions: Function,
areaId: String
},
data() {
return {
tableData: [],
page: {
current: 1,
size: 10,
total: 10
},
form: {},
dialog: false,
personList: [],
}
},
computed: {
...mapState(["user"]),
rules() {
return {
residentId: [{required: true, message: '请选择人员', trigger: 'blur'},],
description: [{required: true, message: '请输入调整说明', trigger: 'blur'},],
doType: [{required: true, message: '请输入调整说明', trigger: 'change'},],
changeIntegral: [
{
required: true, validator: (rule, value, callback) => {
if (!/^[1-9]\d*$/.test(value)) {
callback(new Error('请输入正整数'))
} else {
callback();
}
}, trigger: 'blur'
},],
}
},
colConfigs() {
return [
{prop: "residentName", label: "姓名"},
{prop: "description", label: "调整说明"},
{prop: "changeIntegral", label: "类型", align: "center", render: (h, {row}) => h('p', +row.changeIntegral > 0 ? "加分" : '减分')},
{
prop: "changeIntegral",
label: "积分",
align: "center",
render: (h, {row}) =>h('p',row.changeIntegral > 0 ? `+${row.changeIntegral}` : `${row.changeIntegral}`)
},
{prop: "doTime", label: "操作时间"},
{prop: "declareObjName", label: "操作人", align: "center"},
]
}
},
methods: {
selectPerson(val) {
if (val) {
this.form.residentId = val.id
this.personList = [{...val}]
} else {
this.form.residentId = ""
this.personList = []
}
},
onConfirm() {
this.$refs['form'].validate(valid => {
if (valid) {
this.instance.post(`/app/appvillagerintegraldetail/changeIntegral`, {
...this.form,
changeIntegral: this.form.doType == 0 ? `+${this.form.changeIntegral}` : `-${this.form.changeIntegral}`
}).then(res => {
if (res.code == 0) {
this.$message.success("添加成功")
this.dialog = false
this.getList()
}
})
}
})
},
getList() {
this.instance.post(`/app/appvillagerintegraldetail/list`, null, {
params: {
...this.page,
areaId: this.areaId,
doType: 2
}
}).then(res => {
if (res?.data) {
this.tableData = res.data.records
this.page.total = res.data.total
}
})
}
},
created() {
this.getList()
}
}
</script>
<style lang="scss" scoped>
.scoreChange {
height: 100%;
overflow: auto;
}
</style>

View File

@@ -298,7 +298,7 @@ export default {
},
created() {
this.areaId = this.user.info.areaId;
this.dict.load('integralVillageGroup', 'integralRuleStatus', 'integralPersonType', 'householdRelation', 'residentType');
this.dict.load( 'integralRuleStatus', 'householdRelation', 'residentType');
this.getList();
},
methods: {

View File

@@ -1,7 +1,7 @@
<template>
<ai-detail class="family_detail">
<template slot="title">
<ai-title title="个人积分明细" :isShowBack="true" :isShowBottomBorder="true" @onBackClick="$emit('goBack')" ></ai-title>
<ai-title title="个人积分明细" :isShowBack="true" :isShowBottomBorder="true" @onBackClick="$emit('goBack')"></ai-title>
</template>
<template slot="content">
<div class="detail-info">
@@ -19,37 +19,24 @@
</div>
</div>
<ai-card title="余额变动明细">
<template slot="right">
<!-- <ai-download
:instance="instance"
url="/app/appvillagerintegraldetail/export"
:disabled="!Boolean(tableData.length)"
:params="{familyName:detailInfo.name,doType:doType}"
fileName="余额变动明细">
<span class="iconfont iconExported">导出</span>
</ai-download> -->
</template>
<template #content>
<el-select v-model="doType" placeholder="请选择类型" size='small' clearable @change="page.current=1,getList()">
<el-option
v-for="(item,i) in dict.getDict('integralDetailType')"
:label="item.dictName"
:key="i"
:value="item.dictValue">
</el-option>
</el-select>
<ai-table class="fs-14"
style="margin-top: 16px;"
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
:current.sync="page.current"
:size.sync="page.size"
:isShowPagination="false"
tableSize="small"
:border="true"
@getList="getList">
</ai-table>
<ai-search-bar>
<template #left>
<ai-select v-model="type" placeholder="请选择类型" @change="page.current=1,getList()" :selectList="dict.getDict('integralDetailType')"/>
</template>
<template #right>
<ai-download
:instance="instance"
url="/app/appvillagerintegraldetail/export"
:disabled="!Boolean(tableData.length)"
:params="{residentId:detailInfo.id,type}"
fileName="余额变动明细">
<el-button type="text" icon="iconfont iconExported">导出</el-button>
</ai-download>
</template>
</ai-search-bar>
<ai-table :tableData="tableData" :col-configs="colConfigs"
:total="page.total" border :dict="dict" :current.sync="page.current" :size.sync="page.size" @getList="getList"/>
</template>
</ai-card>
</template>
@@ -57,151 +44,125 @@
</template>
<script>
export default {
name: 'balance',
export default {
name: 'balance',
props: {
detailInfo: {
type: Object,
require: true
props: {
detailInfo: {
type: Object,
require: true
},
instance: Function,
dict: Object
},
data() {
return {
page: {
current: 1,
size: 10,
total: 0
},
instance: Function,
dict: Object
},
info: {},
type: '',
tableData: []
}
},
data () {
return {
page: {
current: 1,
size: 10,
total: 0
},
info: {},
doType: '',
tableData: []
}
},
created () {
this.dict.load('integralDetailType')
this.getList()
},
computed: {
colConfigs () {
const _this = this
return [
{
prop: 'doTime',
align: 'center',
label: '时间',
align:'left'
},
{
prop: 'doType',
align: 'center',
label: '类型',
render (h, {row}) {
return h('span',{}, _this.dict.getLabel('integralDetailType', row.bizType))
created() {
this.dict.load('integralDetailType')
this.getList()
},
computed: {
colConfigs() {
return [
{prop: 'doTime', label: '时间', width: 200},
{prop: "type", label: "类型", dict: "integralDetailType", align: 'center'},
{prop: 'changeIntegral', align: 'center', label: '变动积分', render: (h, {row}) => h('p', `${row.integralCalcType == 1 ? '+' : '-'}${row.changeIntegral}`)},
{prop: 'nowIntegral', align: 'center', label: '剩余积分'},
{prop: 'eventDesc', label: '事件', width: 500}
]
}
},
methods: {
getList() {
this.instance.post(`/app/appresident/detail?id=${this.detailInfo.id}`).then(res => {
if (res?.data) {
this.info = res.data.resident
let {type, info: {id: residentId}} = this
this.instance.post(`/app/appvillagerintegraldetail/IntegralList`, null, {
params: {...this.page, queryType: 1, type, residentId}
}).then(res => {
if (res?.data) {
this.tableData = res.data.records
this.page.total = res.data.total
}
},
{
prop: 'changeIntegral',
align: 'center',
label: '变动积分'
},
{
prop: 'nowIntegral',
align: 'center',
label: '剩余积分'
},
{
prop: 'description',
align: 'center',
label: '事件类型',
align:'left'
}
]
}
},
methods: {
getList () {
this.instance.post(`/app/appresident/detail?id=${this.detailInfo.id}`).then(res => {
if (res.code === 0) {
this.info = res.data.resident
this.instance.post(`/app/appvillagerintegraldetail/IntegralList?bizType=${this.doType}&type=1&residentId=${res.data.resident.id}`, null, {
params: this.page
}).then(res => {
if (res.code === 0) {
this.tableData = res.data.records
}
})
}
})
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.family_detail{
height: 100%;
background-color: #fff;
.family_detail {
height: 100%;
background-color: #fff;
::v-deep .ai-card__body {
padding: 12px 16px 20px!important;
}
.detail-info {
display: flex;
align-items: center;
margin-bottom: 20px;
.detail-info {
display: flex;
align-items: center;
margin-bottom: 20px;
.detail-info__item {
flex: 1;
height: 96px;
margin-right: 20px;
padding: 16px 24px;
background: #FFFFFF;
box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.15);
border-radius: 4px;
.detail-info__item {
flex: 1;
height: 96px;
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;
}
h2 {
margin-bottom: 8px;
color: #888888;
font-size: 16px;
font-weight: bold;
}
span {
display: block;
line-height: 32px;
font-size: 24px;
font-weight: bold;
color: #222;
}
&:last-child {
margin-right: 0;
}
}
.iconExported{
color:#5088FF;
font-size: 12px;
cursor: pointer;
}
.info{
padding: 16px 0 16px 0;
}
.do_type{
height: 56px;
}
.fs-14{
::v-deep .el-table--small{
font-size: 14px!important;
h2 {
margin-bottom: 8px;
color: #888888;
font-size: 16px;
font-weight: bold;
}
span {
display: block;
line-height: 32px;
font-size: 24px;
font-weight: bold;
color: #222;
}
}
}
</style>
.iconExported {
color: #5088FF;
font-size: 12px;
cursor: pointer;
}
.info {
padding: 16px 0 16px 0;
}
.do_type {
height: 56px;
}
.fs-14 {
::v-deep .el-table--small {
font-size: 14px !important;
}
}
}
</style>

View File

@@ -1,29 +1,19 @@
<template>
<section class="AppScoreRules">
<ai-list v-if="$permissions('app_appvillagerintegralrule_detail')">
<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.classification"
@change="search.current = 1, getList()"
placeholder="请选择分类"
:selectList="dict.getDict('atWillReportType')">
</ai-select>
<ai-select
v-model="search.integralType"
@change="search.current = 1, getList()"
placeholder="请选择类型"
:selectList="dict.getDict('integralIntegralType')">
</ai-select>
<ai-select
v-model="search.ruleStatus"
@change="search.current = 1, getList()"
placeholder="请选择状态"
:selectList="dict.getDict('integralRuleStatus')">
v-model="search.status"
@change="page.current = 1, getList()"
placeholder="请选择状态"
:selectList="dict.getDict('integralRuleStatus')">
</ai-select>
</template>
<template slot="right">
@@ -31,113 +21,87 @@
</ai-search-bar>
<ai-search-bar style="margin-top: 16px;">
<template #left>
<el-button type="primary" icon="iconfont iconAdd" @click="addRule">添加</el-button>
<el-button type="primary" icon="iconfont iconAdd" @click="dialog=true">添加</el-button>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
ref="aitableex"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList">
<el-table-column slot="integral" label="分值" align="center">
<template slot-scope="{ row }">
: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">
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>
<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.ruleStatus == 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>
<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-dialog
:title="dialog.title"
:visible.sync="dialog.visible"
:customFooter="true"
:destroyOnClose="true"
@close="init('ruleForm')"
width="520px">
<ai-empty v-else>暂无应用权限</ai-empty>
<ai-dialog :title="dialogTitle" :visible.sync="dialog" @onConfirm="onConfirm" @closed="form={ladderRule: []}" width="700px">
<div class="form_div">
<el-form
ref="ruleForm"
:model="dialogInfo"
:rules="formRules"
size="small"
label-suffix=""
label-width="100px">
<el-form-item label="类别" prop="classification">
<ai-select
size="small"
v-model="dialogInfo.classification"
placeholder="请选择..."
:selectList="dict.getDict('atWillReportType')">
</ai-select>
<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="ruleName">
<el-input placeholder="请输入…" maxlength="30" show-word-limit v-model="dialogInfo.ruleName"></el-input>
<el-form-item label="规则" prop="ruleType" v-if="form.ruleType>-1" required>
<el-row type="flex" justify="space-between">
<div v-text="dict.getLabel('integralRuleRuleType',form.ruleType)"/>
<el-button v-if="form.ruleType==1" type="text" icon="iconfont iconAdd"
@click="form.ladderRule.push({viewCount:null,integral:null})">添加
</el-button>
</el-row>
<el-table v-if="form.ruleType==1" :data="form.ladderRule" size="mini" border stripe>
<el-table-column label="查看人数(人)" align="center">
<template slot-scope="{row}">
<el-input class="tableInput" v-model.number="row.viewCount" clearable placeholder="请输入"/>
</template>
</el-table-column>
<el-table-column label="获得积分(分)" align="center">
<template slot-scope="{row}">
<el-input class="tableInput" v-model="row.integral" clearable placeholder="请输入" type="number"
@keyup.native="row.integral=checkIntegral(row.integral)"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="{row,$index}">
<el-button type="text" @click="handleDelete($index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="规则说明" prop="ruleDescription">
<el-input
type="textarea"
:rows="3"
maxlength="500"
show-word-limit
placeholder="请输入…"
v-model="dialogInfo.ruleDescription">
</el-input>
<el-form-item label="周期范围" prop="scoringCycle">
<ai-select v-model="form.scoringCycle" :selectList="dict.getDict('integralRuleScoringCycle')"/>
</el-form-item>
<el-form-item label="类型" prop="integralType">
<el-radio-group v-model="dialogInfo.integralType">
<el-radio label="1">加分</el-radio>
<el-radio label="0">扣分</el-radio>
</el-radio-group>
</el-form-item>
<!-- <el-form-item label="分值" prop="integralValueType">
<el-radio-group v-model="dialogInfo.integralValueType" @change="numTypeChange">
<el-radio label="0">固定分值</el-radio>
<el-radio label="1">区间分值</el-radio>
</el-radio-group>
</el-form-item> -->
<!-- <el-form-item label="积分" required v-if="dialogInfo.integralValueType == '1'">
<el-col :span="7" style="width: 30%;">
<el-form-item prop="integralStart">
<el-input placeholder="请输入整数" v-model="dialogInfo.integralStart"></el-input>
</el-form-item>
</el-col>
<el-col class="line" :span="1" style="width: 4%;text-align:center;">-</el-col>
<el-col :span="7" style="width: 30%;">
<el-form-item prop="integralEnd">
<el-input placeholder="请输入整数" v-model="dialogInfo.integralEnd"></el-input>
</el-form-item>
</el-col>
<el-col class="line" :span="9" style="width: 36%;"></el-col>
</el-form-item> -->
<el-form-item label="积分" required v-if="dialogInfo.integralValueType == '0'">
<el-form-item prop="integral">
<el-input placeholder="请输入自然数" v-model="dialogInfo.integral"></el-input>
<template v-if="form.ruleType==0">
<el-form-item label="奖励次数" prop="numberLimit">
<el-input placeholder="请输入,周期范围内,不填写表示不限制" v-model.number="form.numberLimit" clearable/>
</el-form-item>
</el-form-item>
<el-form-item label="积分分值" prop="integral">
<el-input placeholder="请输入" v-model="form.integral" clearable/>
</el-form-item>
</template>
</el-form>
</div>
<div class="dialog-footer" slot="footer">
<el-button @click="dialog.visible=false" size="medium">取消</el-button>
<el-button @click="onConfirm('ruleForm')" type="primary" size="medium">确认</el-button>
</div>
</ai-dialog>
</section>
</template>
@@ -149,169 +113,91 @@ export default {
props: {
instance: Function,
dict: Object,
permissions: Function
},
data() {
var integralPass = (rule, value, callback) => {
if (value) {
if ((/(^[0-9]\d*$)/.test(value))) {
callback();
} else {
callback(new Error("请输入自然数"));
}
} else {
callback(new Error("请输入积分"));
}
};
var integralStartPass = (rule, value, callback) => {
if (value) {
if ((/(^[1-9]\d*$)/.test(value))) {
callback();
} else {
callback(new Error("请输入整数积分"));
}
} else {
callback(new Error("请输入积分"));
}
};
var integralEndPass = (rule, value, callback) => {
if (value) {
if ((/(^[1-9]\d*$)/.test(value))) {
if (Number(value) < Number(this.dialogInfo.integralStart)) {
callback(new Error("请输入大于前面数字的积分"));
} else {
callback()
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)
})
}
} else {
callback(new Error("请输入整数积分"));
}
} else {
callback(new Error("请输入积分"));
}
};
},
},
data() {
return {
search: {
current: 1,
size: 10,
classification: "",
integralType: "",
ruleStatus: "",
},
total: 10,
search: {status: "", eventType: null},
page: {current: 1, size: 10, total: 0},
colConfigs: [
{
prop: "classification", label: "类型", width: 168,
formart: (classification) =>
this.dict.getLabel("atWillReportType", classification),
},
{prop: "ruleName", label: "事项", "show-overflow-tooltip": true, width: 260},
{prop: "ruleDescription", label: "规则说明", width: 390},
{
prop: "integralType",
label: "类型",
width: 60,
formart: (integralType) =>
this.dict.getLabel("integralIntegralType", integralType),
},
{slot: "integral", label: "分值", width: 70},
{prop: "doTime", label: "最后编辑时间", width: 160},
{prop: "doUserName", label: "操作人", width: 120},
{
prop: "ruleStatus",
label: "状态",
align: "center",
width: 96,
fixed: "right",
render: (h, params) => {
return h(
"span",
{
class: "status-" + params.row.ruleStatus,
},
this.dict.getLabel("integralRuleStatus", params.row.ruleStatus)
);
},
},
{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"},
],
tableData: [],
dialog: {
title: "",
visible: false,
},
dialogInfo: {
classification: "",
ruleName: "",
ruleDescription: "",
integralType: '1',
integralValueType: '0',
integral: "",
// integralStart: "",
// integralEnd: "",
doTime: '',
id: '',
doUserId: '',
doUserName: '',
},
dialog: false,
form: {ladderRule: []},
formRules: {
classification: [
{required: true, message: "请选择类型", trigger: "change"},
],
ruleName: [{required: true, message: "请输入事项", trigger: "blur"}],
ruleDescription: [
{required: true, message: "请输入规则说明", trigger: "blur"},
],
integralType: [
{required: true, message: "请选择类型", trigger: "change"},
],
integralValueType: [
{required: true, message: "请选择分值类型", trigger: "change"},
],
integral: [
{required: true, validator: integralPass, trigger: "change"},
],
integralStart: [
{required: true, validator: integralStartPass, trigger: "change"},
],
integralEnd: [
{required: true, validator: integralEndPass, trigger: "change"},
],
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: []
};
},
created() {
this.dict.load(["classification", "integralIntegralType", "integralRuleStatus", 'atWillReportType']).then(() => {
this.dict.load("integralRuleStatus", "integralRuleRuleType", 'integralRuleScoringCycle', 'integralRuleEvent', 'integralRuleEventType').then(() => {
this.getList();
});
},
methods: {
getList() {
this.instance
.post(`/app/appvillagerintegralrule/list`, null, {
params: {
...this.search,
},
})
.then((res) => {
if (res.code == 0) {
this.instance.post(`/app/appvillagerintegralrule/list`, null, {
params: {...this.search, ...this.page},
}).then(res => {
if (res?.data) {
this.tableData = res.data.records;
this.total = res.data.total;
this.page.total = res.data.total;
}
});
},
toEdit(row) {
this.dialog.title = "编辑积分规则";
this.dialog.visible = true;
this.dialogInfo = {...row}
this.dialogInfo.integralStart = Math.abs(this.dialogInfo.integralStart)
this.dialogInfo.integralEnd = Math.abs(this.dialogInfo.integralEnd)
this.dialogInfo.integral = Math.abs(this.dialogInfo.integral)
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
})
})
},
remove(id) {
this.$confirm("删除后不可恢复,是否要删除该事项?", {
type: 'error'
@@ -326,13 +212,10 @@ export default {
});
});
},
changeStatus(id, status) {
var text = status == 1 ? '启用' : '停用'
let text = status == 1 ? '启用' : '停用'
this.$confirm(`确定${text}该条规则?`).then(() => {
this.instance
.post(`/app/appvillagerintegralrule/enableOrDisable?id=${id}`)
.then((res) => {
this.instance.post(`/app/appvillagerintegralrule/enableOrDisable?id=${id}`).then((res) => {
if (res.code == 0) {
this.$message.success(`${text}成功!`)
this.getList();
@@ -340,36 +223,27 @@ export default {
});
});
},
onReset() {
this.search.current = 1
this.page.current = 1
this.search.classification = ""
this.search.integralType = ""
this.search.ruleStatus = ""
this.getList();
},
onAdd() {
this.$emit("change", {
type: "add",
});
},
addRule() {
this.dialog.title = "添加积分规则";
this.dialog.visible = true;
},
onConfirm(formName) {
this.$refs[formName].validate((valid) => {
onConfirm() {
if(this.form.ruleType==1 && !this.form.ladderRule.length) {
return this.$message.error('请添加规则')
}
this.$refs.DialogForm.validate((valid) => {
if (valid) {
this.instance
.post(`/app/appvillagerintegralrule/addOrUpdate`, this.dialogInfo)
.then((res) => {
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.dialogInfo.id ? '编辑成功' : '添加成功'}`)
this.$message.success(`${this.isEdit ? '编辑成功' : '添加成功'}`)
this.onReset()
this.onCancel();
this.dialog = false;
}
});
} else {
@@ -377,48 +251,53 @@ export default {
}
});
},
onCancel() {
this.dialog.visible = false;
handleTypeSearch(v) {
this.search.event = v?.[0]
this.search.type = v?.[1]
this.page.current = 1
this.$refs.eventTypeSearch.dropDownVisible = false
this.getList()
},
numTypeChange() {
// this.dialogInfo.integra = "";
// this.dialogInfo.integralStart = "";
// this.dialogInfo.integralEnd = "";
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
}
},
init(formName) {
this.$refs[formName].clearValidate();
Object.keys(this.dialogInfo).forEach((e) => {
this.dialogInfo[e] = "";
});
this.dialogInfo.integralType = '1'
this.dialogInfo.integralValueType = '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">
<style lang="scss" scoped>
.AppScoreRules {
height: 100%;
background: #f3f6f9;
.cur-p {
cursor: pointer;
}
::v-deep .ai-list__content--right {
width: 100%;
}
.status-0 {
color: #ff4466;
}
::v-deep .ai-dialog {
.el-cascader {
width: 100%;
}
.status-1 {
color: #2ea222;
.tableInput {
& > input {
text-align: center;
border: none;
background: transparent;
}
}
}
}
</style>

View File

@@ -9,60 +9,57 @@
<template #content>
<div class="form_div">
<el-form
ref="rules"
:model="forms"
:rules="formRules"
size="small"
label-suffix=""
label-width="100px">
ref="rules"
:model="forms"
:rules="formRules"
size="small"
label-suffix=""
label-width="100px">
<el-form-item label="店铺名称" prop="shopId">
<el-select
v-model="forms.shopId"
placeholder="请选择..."
clearable>
v-model="forms.shopId"
placeholder="请选择..."
clearable>
<el-option
v-for="(item, i) in shopList"
:key="i"
:label="item.shopName"
:value="item.id">
v-for="(item, i) in shopList"
:key="i"
:label="item.shopName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="商品类型" prop="merchandiseType">
<el-select
v-model="forms.merchandiseType"
placeholder="请选择..."
clearable>
v-model="forms.merchandiseType"
placeholder="请选择..."
clearable>
<el-option
v-for="(item, i) in dict.getDict('integralMerchandiseType')"
:key="i"
:label="item.dictName"
:value="item.dictValue">
v-for="(item, i) in dict.getDict('integralMerchandiseType')"
:key="i"
:label="item.dictName"
:value="item.dictValue">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="商品名称" prop="merchandiseName">
<el-input
v-model="forms.merchandiseName"
placeholder="请输入..."
maxlength="100"
show-word-limit>
v-model="forms.merchandiseName"
placeholder="请输入..."
maxlength="100"
show-word-limit>
</el-input>
</el-form-item>
<div class="above">
<div class="left">
<el-form-item label="单价" prop="costIntegral">
<el-input
v-model="forms.costIntegral"
placeholder="请输入..."
></el-input>
<el-input v-model="forms.costIntegral" placeholder="请输入..."/>
</el-form-item>
</div>
<div class="right">
<el-form-item label="库存" prop="inventoryNumber">
<el-input
v-model="forms.inventoryNumber"
placeholder="请输入...">
v-model="forms.inventoryNumber"
placeholder="请输入...">
</el-input>
</el-form-item>
</div>
@@ -76,21 +73,21 @@
<el-form-item label="商品图片" prop="fileList" ref="fileList">
<div class="upload">
<ai-uploader
:instance="instance"
@change="changeFile"
v-model="forms.fileList"
:limit="9">
:instance="instance"
@change="changeFile"
v-model="forms.fileList"
:limit="9">
</ai-uploader>
</div>
</el-form-item>
<el-form-item label="商品详情" prop="description">
<el-input
v-model="forms.description"
type="textarea"
:rows="5"
maxlength="100"
show-word-limit
placeholder="请输入...">
v-model="forms.description"
type="textarea"
:rows="5"
maxlength="100"
show-word-limit
placeholder="请输入...">
</el-input>
</el-form-item>
</el-form>
@@ -105,49 +102,47 @@
<ai-wrapper label-width="70px" :columnsNumber="1">
<ai-info-item label="店铺名称"><span>{{ forms.shopName }}</span></ai-info-item>
<ai-info-item label="商品类型"
><span>{{
><span>{{
dict.getLabel("integralMerchandiseType", forms.merchandiseType)
}}</span></ai-info-item
>
<ai-info-item label="商品名称"
><span>{{ forms.merchandiseName }}</span></ai-info-item
><span>{{ forms.merchandiseName }}</span></ai-info-item
>
</ai-wrapper>
<ai-wrapper label-width="70px" :columnsNumber="2">
<ai-info-item label="单价"
><span>{{ forms.costIntegral + "积分" }}</span></ai-info-item
>
<ai-info-item label="单价"><span>{{ forms.costIntegral + "积分" }}</span></ai-info-item>
<ai-info-item label="库存"
><span>{{ forms.inventoryNumber }}</span></ai-info-item
><span>{{ forms.inventoryNumber }}</span></ai-info-item
>
<ai-info-item label="销量"
><span>{{ forms.saleNumber || "0" }}</span></ai-info-item
><span>{{ forms.saleNumber || "0" }}</span></ai-info-item
>
</ai-wrapper>
<ai-wrapper label-width="70px" :columnsNumber="1">
<ai-info-item label="状态"
><span
><span
:style="{
color: dict.getColor(
'integralMerchandiseStatus',
forms.status
),
}"
>{{
dict.getLabel("integralMerchandiseStatus", forms.status)
}}</span
></ai-info-item
>{{
dict.getLabel("integralMerchandiseStatus", forms.status)
}}</span
></ai-info-item
>
<ai-info-item label="商品图片">
<ai-uploader
:disabled="true"
:instance="instance"
v-model="forms.fileList"
:limit="9"
:disabled="true"
:instance="instance"
v-model="forms.fileList"
:limit="9"
></ai-uploader>
</ai-info-item>
<ai-info-item label="商品详情"
><span>{{ forms.description }}</span></ai-info-item
><span>{{ forms.description }}</span></ai-info-item
>
</ai-wrapper>
</div>
@@ -163,7 +158,8 @@
</template>
<script>
import { mapState } from "vuex";
import {mapState} from "vuex";
export default {
name: "addGoods",
props: {
@@ -206,34 +202,23 @@ export default {
callback(new Error("请输入单价"));
}
};
var integral2 = (rule, value, callback) => {
if (value) {
if (/^[1-9]\d*$/.test(value)) {
callback();
} else {
callback(new Error("请输入正整数"));
}
} else {
callback(new Error("请输入库存"));
}
};
return {
shopId: [{ required: true, message: "请选择店铺", trigger: "change" }],
shopId: [{required: true, message: "请选择店铺", trigger: "change"}],
merchandiseType: [
{ required: true, message: "请选择商品类型", trigger: "change" },
{required: true, message: "请选择商品类型", trigger: "change"},
],
merchandiseName: [
{ required: true, message: "请输入商品名称", trigger: "blur" },
],
costIntegral: [
{ required: true, validator: integral, trigger: "blur" },
{required: true, message: "请输入商品名称", trigger: "blur"},
],
inventoryNumber: [
{ required: true, validator: integral2, trigger: "blur" },
{required: true, validator: integral, trigger: "blur"},
],
status: [{ required: true, message: "请选择状态", trigger: "change" }],
costIntegral: [
{required: true, pattern: /^\d*[.\d]\d?$/, message: "请输入正数,最多保留一位小数", trigger: "blur"},
],
status: [{required: true, message: "请选择状态", trigger: "change"}],
fileList: [
{ required: true, message: "请上传商品图片", trigger: "change" },
{required: true, message: "请上传商品图片", trigger: "change"},
],
};
},
@@ -264,18 +249,18 @@ export default {
getShopList() {
return new Promise((reslove) => {
this.instance
.post(`/app/appvillagerintegralshop/listForOperator`, null, {
params: {
size: 100000,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.shopList = res.data.records;
reslove();
}
});
.post(`/app/appvillagerintegralshop/listForOperator`, null, {
params: {
size: 100000,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.shopList = res.data.records;
reslove();
}
});
});
},
changeFile() {
@@ -283,22 +268,22 @@ export default {
},
searchDetail(id) {
this.instance
.post(`/app/appvillagerintegralmerchandise/queryDetailById`, null, {
params: {
id,
},
})
.then((res) => {
if (res.code == 0) {
this.forms = { ...res.data };
let i = this.shopList.findIndex(
.post(`/app/appvillagerintegralmerchandise/queryDetailById`, null, {
params: {
id,
},
})
.then((res) => {
if (res.code == 0) {
this.forms = {...res.data};
let i = this.shopList.findIndex(
(item) => item.id == this.forms.shopId
);
if (i > -1) {
this.forms.shopName = this.shopList[i].shopName;
}
);
if (i > -1) {
this.forms.shopName = this.shopList[i].shopName;
}
});
}
});
},
edit() {
this.isEdit = false;
@@ -307,24 +292,24 @@ export default {
this.$refs[formName].validate((valid) => {
if (valid) {
this.instance
.post(
.post(
`/app/appvillagerintegralmerchandise/addOrUpdate`,
{
...this.forms,
areaId: this.user.info.areaId,
},
null
)
.then((res) => {
if (res.code == 0) {
this.$message.success("提交成功");
if (type == "detail") {
this.isEdit = true;
} else {
this.$emit("goBack");
}
)
.then((res) => {
if (res.code == 0) {
this.$message.success("提交成功");
if (type == "detail") {
this.isEdit = true;
} else {
this.$emit("goBack");
}
});
}
});
} else {
return false;
}
@@ -337,21 +322,26 @@ export default {
<style lang="scss" scoped>
.add_order {
height: 100%;
.form_div {
padding: 16px 0;
}
.above {
overflow: hidden;
width: 100%;
.left {
width: 50%;
float: left;
}
.right {
width: 50%;
float: right;
}
}
.iconEdit,
.Edit {
color: #5088ff;
@@ -359,8 +349,9 @@ export default {
cursor: pointer;
padding-left: 8px;
}
.info {
padding: 16px 0;
}
}
</style>
</style>

View File

@@ -9,45 +9,47 @@
<template #content>
<div class="form_div">
<el-form
ref="rules"
:model="forms"
:rules="formRules"
size="small"
label-suffix=""
label-width="100px">
ref="rules"
:model="forms"
:rules="formRules"
size="small"
label-suffix=""
label-width="100px">
<el-form-item label="店铺名称" prop="shopId">
<el-select
v-model="forms.shopId"
placeholder="请选择..."
@change="(forms.merchandiseList = []), (goodIntegral = {})"
clearable>
v-model="forms.shopId"
placeholder="请选择..."
@change="(forms.merchandiseList = []), (goodIntegral = {})"
clearable>
<el-option
v-for="(item, i) in shopList"
:key="i"
:label="item.shopName"
:value="item.id">
v-for="(item, i) in shopList"
:key="i"
:label="item.shopName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="兑换家庭" prop="name">
<el-row type="flex" :gutter="8">
<el-col
><el-input v-model="forms.name" disabled clearable
/></el-col>
>
<el-input v-model="forms.name" disabled clearable
/>
</el-col>
<el-col>
<ai-person-select
:instance="instance"
url="/app/appvillagerintegralfamilymember/list"
headerTitle="家庭列表"
dialogTitle="选择家庭"
@selectPerson="getSelect"
:instance="instance"
url="/app/appvillagerintegralfamilymember/list"
headerTitle="家庭列表"
dialogTitle="选择家庭"
@selectPerson="getSelect"
>
<template name="option" v-slot:option="{ item }">
<span class="iconfont iconProlife">{{ item.name }}</span>
<ai-id
mode="show"
:show-eyes="false"
:value="item.idNumber"
mode="show"
:show-eyes="false"
:value="item.idNumber"
/>
<span>{{ item.phone }}</span>
</template>
@@ -65,40 +67,40 @@
<el-button @click="showGoodsList()" :disabled="!forms.shopId || !forms.name">选择商品</el-button>
</el-form-item>
<ai-table
:tableData="forms.merchandiseList"
:col-configs="colConfigs"
:isShowPagination="false">
:tableData="forms.merchandiseList"
:col-configs="colConfigs"
:isShowPagination="false">
<el-table-column
label="商品图"
slot="photo"
align="center"
width="150">
label="商品图"
slot="photo"
align="center"
width="150">
<template v-slot="{ row }">
<ai-uploader
:disabled="true"
:instance="instance"
v-model="row.photo"
:limit="9">
:disabled="true"
:instance="instance"
v-model="row.photo"
:limit="9">
</ai-uploader>
</template>
</el-table-column>
<el-table-column
label="兑换数量"
width="180"
slot="merchandiseNumber"
align="center">
label="兑换数量"
width="180"
slot="merchandiseNumber"
align="center">
<template v-slot="{ row }">
<el-input-number
:min="1"
:max="row.inventoryNumber"
size="mini"
v-model="merchandiseNumbers[row.id]"
@change="
:min="1"
:max="row.inventoryNumber"
size="mini"
v-model="merchandiseNumbers[row.id]"
@change="
(currentValue, oldValue) =>
changeNumber(currentValue, oldValue, row)
"
:step="1"
step-strictly
:step="1"
step-strictly
></el-input-number>
</template>
</el-table-column>
@@ -108,18 +110,18 @@
</template>
</el-table-column>
<el-table-column
slot="options"
label="操作"
align="center"
width="60"
slot="options"
label="操作"
align="center"
width="60"
>
<template slot-scope="row">
<el-button
type="text"
class="icon-color89B"
icon="iconfont iconDelete"
title="删除"
@click="deleteGood(row)"
type="text"
class="icon-color89B"
icon="iconfont iconDelete"
title="删除"
@click="deleteGood(row)"
/>
</template>
</el-table-column>
@@ -149,33 +151,33 @@
<ai-info-item label="店铺名"><span>{{ detailInfo.shopName }}</span></ai-info-item>
<ai-info-item label="状态">
<span :style="{ color: dict.getColor('integralOrderStatus', detailInfo.orderStatus)}">
{{ dict.getLabel("integralOrderStatus", detailInfo.orderStatus)}}
{{ dict.getLabel("integralOrderStatus", detailInfo.orderStatus) }}
</span>
</ai-info-item>
</ai-wrapper>
<ai-table
:tableData="detailInfo.merchandiseList"
:col-configs="colConfigs"
:isShowPagination="false">
:tableData="detailInfo.merchandiseList"
:col-configs="colConfigs"
:isShowPagination="false">
<el-table-column
label="商品图"
slot="photo"
align="center"
width="150">
label="商品图"
slot="photo"
align="center"
width="150">
<template v-slot="{ row }">
<ai-uploader
:disabled="true"
:instance="instance"
v-model="row.merchandisePhoto"
:limit="9">
:disabled="true"
:instance="instance"
v-model="row.merchandisePhoto"
:limit="9">
</ai-uploader>
</template>
</el-table-column>
<el-table-column
label="兑换数量"
width="200"
slot="merchandiseNumber"
align="center">
label="兑换数量"
width="200"
slot="merchandiseNumber"
align="center">
<template v-slot="{ row }">
{{ row.merchandiseNumber }}
</template>
@@ -227,47 +229,34 @@
</template>
</ai-detail>
<ai-dialog
title="选择商品"
:visible.sync="showGoods"
:customFooter="true"
:destroyOnClose="true"
class="goods"
@close="init"
border
width="780px">
title="选择商品"
:visible.sync="showGoods"
:customFooter="true"
:destroyOnClose="true"
class="goods"
@close="init"
border
width="780px">
<div class="border_div">
<header>
<span>商品列表</span>
<el-input
v-model="keyWord"
size="mini"
placeholder="商品关键字"
@keyup.enter.native="showGoodsList()"
clearable
style="width: 220px"
suffix-icon="iconfont iconSearch"
v-model="keyWord"
size="mini"
placeholder="商品关键字"
@keyup.enter.native="showGoodsList()"
clearable
style="width: 220px"
suffix-icon="iconfont iconSearch"
/>
</header>
<ai-table
:tableData="goodList"
:col-configs="goodsConfig"
:isShowPagination="false"
@selection-change="handleSelectionChange"
:tableData="goodList"
:col-configs="goodsConfig"
:isShowPagination="false"
@selection-change="handleSelectionChange"
>
<el-table-column
slot="selection"
type="selection"
width="55"
:selectable="
(row, index) => {
if (Number(row.inventoryNumber) > 0) {
return true;
} else {
return false;
}
}
"
></el-table-column>
<el-table-column slot="selection" type="selection" width="55" :selectable="(row)=>Number(row.inventoryNumber)>0"/>
</ai-table>
</div>
<div class="dialog-footer" slot="footer">
@@ -279,7 +268,8 @@
</template>
<script>
import { mapState } from "vuex";
import {mapState} from "vuex";
export default {
name: "addOrder",
props: {
@@ -316,18 +306,18 @@ export default {
...mapState(["user"]),
formRules() {
return {
shopId: [{ required: true, message: "请选择店铺", trigger: "change" }],
shopId: [{required: true, message: "请选择店铺", trigger: "change"}],
name: [
{ required: true, message: "请选择兑换家庭", trigger: "change" },
{required: true, message: "请选择兑换家庭", trigger: "change"},
],
merchandiseList: [
{ required: true, message: "请选择商品", trigger: "change" },
{required: true, message: "请选择商品", trigger: "change"},
],
};
},
colConfigs() {
return [
{ slot: "photo", prop: "photo", label: "商品图", align: "center" },
{slot: "photo", prop: "photo", label: "商品图", align: "center"},
{
prop: "merchandiseName",
label: "商品名",
@@ -360,15 +350,15 @@ export default {
label: "消耗积分",
align: "center",
},
{ slot: "options", label: "操作", align: "center" },
{slot: "options", label: "操作", align: "center"},
];
},
goodsConfig() {
return [
{ slot: "selection", label: "", align: "center" },
{ prop: "merchandiseName", label: "商品名", align: "left", width: 350 },
{ prop: "costIntegral", label: "单价", align: "left" },
{ prop: "inventoryNumber", align: "center", label: "库存" },
{slot: "selection", label: "", align: "center"},
{prop: "merchandiseName", label: "商品名", align: "left", width: 350},
{prop: "costIntegral", label: "单价", align: "left"},
{prop: "inventoryNumber", align: "center", label: "库存"},
];
},
allIntegral() {
@@ -424,13 +414,14 @@ export default {
this.$confirm("是否删除该商品?", {
type: "error",
})
.then(() => {
this.forms.merchandiseList.splice(row.$index, 1);
this.$delete(this.goodIntegral, row.row.id);
this.$delete(this.merchandiseNumbers, row.row.id);
return this.$message.success("删除成功");
})
.catch(() => {});
.then(() => {
this.forms.merchandiseList.splice(row.$index, 1);
this.$delete(this.goodIntegral, row.row.id);
this.$delete(this.merchandiseNumbers, row.row.id);
return this.$message.success("删除成功");
})
.catch(() => {
});
},
selectGoodsInit(val) {
return new Promise((reslove) => {
@@ -441,7 +432,7 @@ export default {
this.$set(this.goodIntegral, e.id, Number(e.costIntegral));
if (e.photo) {
e.merchandisePhoto = e.photo;
e.photo = [{ ...JSON.parse(e.photo)[0] }];
e.photo = [{...JSON.parse(e.photo)[0]}];
} else {
e.photo = [];
}
@@ -454,51 +445,51 @@ export default {
},
showGoodsList() {
this.instance
.post(`/app/appvillagerintegralmerchandise/list`, null, {
params: {
size: 100000,
shopId: this.forms.shopId,
merchandiseName: this.keyWord,
status: "1",
},
})
.then((res) => {
if (res.code == 0) {
if (this.forms.merchandiseList.length > 0) {
this.forms.merchandiseList.forEach((e1, index1) => {
res.data.records.forEach((e2, index2) => {
if (e1.id == e2.id) {
res.data.records.splice(index2, 1);
}
});
.post(`/app/appvillagerintegralmerchandise/list`, null, {
params: {
size: 100000,
shopId: this.forms.shopId,
merchandiseName: this.keyWord,
status: "1",
},
})
.then((res) => {
if (res.code == 0) {
if (this.forms.merchandiseList.length > 0) {
this.forms.merchandiseList.forEach((e1, index1) => {
res.data.records.forEach((e2, index2) => {
if (e1.id == e2.id) {
res.data.records.splice(index2, 1);
}
});
}
this.goodList = res.data.records;
this.showGoods = true;
});
}
});
this.goodList = res.data.records;
this.showGoods = true;
}
});
},
changeNumber(currentValue, oldValue, row) {
console.log(currentValue, oldValue, row);
this.$set(
this.goodIntegral,
row.id,
Number(currentValue) * Number(row.costIntegral)
this.goodIntegral,
row.id,
Number(currentValue) * Number(row.costIntegral)
);
},
getShopList() {
this.instance
.post(`/app/appvillagerintegralshop/listForOperator`, null, {
params: {
size: 100000,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.shopList = res.data.records;
}
});
.post(`/app/appvillagerintegralshop/listForOperator`, null, {
params: {
size: 100000,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.shopList = res.data.records;
}
});
},
save(formName) {
this.$refs[formName].validate((valid) => {
@@ -507,13 +498,13 @@ export default {
Object.keys(this.merchandiseNumbers).forEach((e2, index2) => {
if (e1.id == e2) {
this.forms.merchandiseList[
index1
].merchandiseNumber = this.merchandiseNumbers[e2];
index1
].merchandiseNumber = this.merchandiseNumbers[e2];
}
});
});
this.instance
.post(
.post(
`/app/appvillagerintegralshoporder/addOrder`,
{
...this.forms,
@@ -521,15 +512,15 @@ export default {
orderIntegral: this.allIntegral,
},
null
)
.then((res) => {
if (res.code == 0) {
this.$message.success("提交成功");
this.$emit("goBack");
} else {
return this.$message.error(res.msg);
}
});
)
.then((res) => {
if (res.code == 0) {
this.$message.success("提交成功");
this.$emit("goBack");
} else {
return this.$message.error(res.msg);
}
});
} else {
return false;
}
@@ -537,20 +528,20 @@ export default {
},
searchDetail(id) {
this.instance
.post(`/app/appvillagerintegralshoporder/queryDetailById`, null, {
params: {
id,
},
})
.then((res) => {
if (res.code == 0) {
this.detailInfo = { ...res.data };
this.detailInfo.merchandiseList.map((e) => {
let arr = JSON.parse(e.merchandisePhoto);
e.merchandisePhoto = [{ ...arr[0] }];
});
}
});
.post(`/app/appvillagerintegralshoporder/queryDetailById`, null, {
params: {
id,
},
})
.then((res) => {
if (res.code == 0) {
this.detailInfo = {...res.data};
this.detailInfo.merchandiseList.map((e) => {
let arr = JSON.parse(e.merchandisePhoto);
e.merchandisePhoto = [{...arr[0]}];
});
}
});
},
},
};
@@ -559,31 +550,39 @@ export default {
<style lang="scss" scoped>
.add_order {
height: 100%;
.form_div {
padding: 16px 0;
}
.goods {
::v-deep .el-table td {
border-bottom: none;
padding: 2px 0;
}
::v-deep .el-table th {
padding: 2px 0;
}
}
.total {
width: 100%;
padding: 32px 0;
p {
text-align: right;
font-size: 14px;
}
.num {
font-size: 14px;
color: #333333;
span:nth-child(1) {
color: #999999;
}
span:nth-child(2) {
color: #999999;
color: #2266ff;
@@ -591,14 +590,17 @@ export default {
font-weight: bold;
}
}
.tip {
color: #ff4466;
}
}
.border_div {
overflow: hidden;
border-radius: 2px;
border: 1px solid #d0d4dc;
header {
height: 40px;
background: #f5f5f5;
@@ -608,14 +610,16 @@ export default {
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #d0d4dc;
span {
color: #333333;
font-size: 12px;
}
}
}
.info {
padding: 16px 0;
}
}
</style>
</style>

View File

@@ -5,61 +5,60 @@
<ai-search-bar>
<template slot="left">
<el-select
size="small"
v-model="searchObj.shopId"
placeholder="请选择店铺"
clearable
@change="(page.current = 1), getList()">
size="small"
v-model="searchObj.shopId"
placeholder="请选择店铺"
clearable
@change="(page.current = 1), getList()">
<el-option
v-for="(item, i) in shopList"
:key="i"
:label="item.shopName"
:value="item.id">
v-for="(item, i) in shopList"
:key="i"
:label="item.shopName"
:value="item.id">
</el-option>
</el-select>
<el-select
size="small"
v-model="searchObj.orderStatus"
placeholder="请选择状态"
clearable
@change="(page.current = 1), getList()">
size="small"
v-model="searchObj.orderStatus"
placeholder="请选择状态"
clearable
@change="(page.current = 1), getList()">
<el-option
v-for="(item, i) in dict.getDict('integralOrderStatus')"
:key="i"
:label="item.dictName"
:value="item.dictValue">
v-for="(item, i) in dict.getDict('integralOrderStatus')"
:key="i"
:label="item.dictName"
:value="item.dictValue">
</el-option>
</el-select>
<div class="times_div">
<p class="times">创建时间</p>
<ai-search label="创建时间">
<el-date-picker
v-model="searchObj.createTimeStart"
type="date"
size="small"
@change="(page.current = 1), getList()"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="开始日期">
v-model="searchObj.createTimeStart"
type="date"
size="small"
@change="(page.current = 1), getList()"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="开始日期">
</el-date-picker>
<el-date-picker
v-model="searchObj.createTimeEnd"
type="date"
size="small"
@change="(page.current = 1), getList()"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="结束日期">
v-model="searchObj.createTimeEnd"
type="date"
size="small"
@change="(page.current = 1), getList()"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="结束日期">
</el-date-picker>
</div>
</ai-search>
</template>
<template slot="right">
<el-input
v-model="searchObj.name"
size="small"
placeholder="订单号/商品名/兑换家庭"
v-throttle="() => {page.current = 1, getList()}"
@clear="page.current = 1, searchObj.name = '', getList()"
clearable
suffix-icon="iconfont iconSearch"
v-model="searchObj.name"
size="small"
placeholder="订单号/商品名/兑换家庭"
v-throttle="() => {page.current = 1, getList()}"
@clear="page.current = 1, searchObj.name = '', getList()"
clearable
suffix-icon="iconfont iconSearch"
/>
</template>
</ai-search-bar>
@@ -67,18 +66,18 @@
<template slot="left">
<!-- <el-button type="primary" icon="iconfont iconAdd" @click="add()">添加</el-button> -->
<ai-download
:instance="instance"
url="/app/appvillagerintegralshoporder/listExport"
:params="{ ...searchObj, areaId: areaId, ids: ids.join(',') }"
fileName="订单管理"
v-if="$permissions('app_appvillagerintegralshoporder_export')">
:instance="instance"
url="/app/appvillagerintegralshoporder/listExport"
:params="{ ...searchObj, areaId: areaId, ids: ids.join(',') }"
fileName="订单管理"
v-if="$permissions('app_appvillagerintegralshoporder_export')">
</ai-download>
<el-dropdown @command="handleCommand">
<el-button type="primary">
变更状态<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="1">批量完成</el-dropdown-item>
<el-dropdown-item command="1">批量兑换</el-dropdown-item>
<el-dropdown-item command="2">批量取消</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
@@ -86,30 +85,29 @@
<template slot="right"></template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
ref="aitableex"
:current.sync="page.current"
@select="onRowClick"
@select-all="onRowClick"
row-key="id"
:default-expand-all="false"
:tree-props="{ children: 'merchandiseList' }"
:size.sync="page.size"
@getList="getList">
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
:current.sync="page.current"
@select="onRowClick"
@select-all="onRowClick"
row-key="id"
:default-expand-all="false"
:tree-props="{ children: 'merchandiseList' }"
:size.sync="page.size"
@getList="getList">
<el-table-column
align="center"
type="selection"
:selectable="(row,index)=>row.orderStatus==0"
width="55"
slot="selection">
align="center"
type="selection"
:selectable="(row,index)=>row.orderStatus==0"
width="55"
slot="selection">
</el-table-column>
<el-table-column
label="订单号/创建时间"
slot="orderCode"
align="center"
width="150">
label="订单号/创建时间"
slot="orderCode"
align="center"
width="150">
<template v-slot="{ row }">
<el-row>
<el-col>{{ row.orderCode }}</el-col>
@@ -118,16 +116,16 @@
</template>
</el-table-column>
<el-table-column
label="商品图"
slot="merchandisePhoto"
align="center"
width="130">
label="商品图"
slot="merchandisePhoto"
align="center"
width="130">
<template v-slot="{ row }">
<ai-uploader
:disabled="true"
:instance="instance"
v-model="row.merchandisePhoto"
:limit="9">
:disabled="true"
:instance="instance"
v-model="row.merchandisePhoto"
:limit="9">
</ai-uploader>
</template>
</el-table-column>
@@ -144,30 +142,30 @@
<el-row>
<el-col style="width: 100%">{{ row.createUserName }}</el-col>
<el-col style="color: #999999">{{
row.createUserPhone
row.createUserPhone
}}
</el-col>
</el-row>
</template>
</el-table-column>
<el-table-column
label="订单状态"
slot="orderStatus"
align="center"
width="130"
fixed="right">
label="订单状态"
slot="orderStatus"
align="center"
width="130"
fixed="right">
<template v-slot="{ row }">
<el-row v-if="row.isParent">
<el-col
style="width: 100%"
:style="{
style="width: 100%"
:style="{
color: dict.getColor(
'integralOrderStatus',
row.orderStatus
),
}"
>{{
dict.getLabel("integralOrderStatus", row.orderStatus)
dict.getLabel("integralOrderStatus", row.orderStatus)
}}
</el-col
>
@@ -177,11 +175,11 @@
>
<el-col style="color: #2266ff; width: 100%" v-if="row.remark">
<el-tooltip
:disabled="!row.remark"
class="item"
effect="light"
:content="row.remark"
placement="left-end"
:disabled="!row.remark"
class="item"
effect="light"
:content="row.remark"
placement="left-end"
>
<el-link type="primary">备注</el-link>
</el-tooltip>
@@ -190,21 +188,20 @@
</template>
</el-table-column>
<el-table-column
label="操作"
slot="options"
align="center"
width="120"
fixed="right">
label="操作"
slot="options"
align="center"
width="120"
fixed="right">
<template v-slot="{ row }">
<div class="table-options">
<el-button
v-if="row.orderCode"
type="text"
@click="goDetail(row)"
title="详情"
:disabled="!$permissions('app_appvillagerintegralshoporder_detail')">
详情
<el-button v-if="row.orderCode" type="text" @click="goDetail(row)" title="详情"
:disabled="!$permissions('app_appvillagerintegralshoporder_detail')">详情
</el-button>
<template v-if="row.orderStatus==0 || row.orderStatus==3">
<el-button type="text" v-if="row.orderStatus==0" @click="handlePendingOrder(row.id,1)">确认兑换</el-button>
<el-button type="text" v-if="row.orderStatus==0 || row.orderStatus==3" @click="handlePendingOrder(row.id,2)">取消订单</el-button>
</template>
</div>
</template>
</el-table-column>
@@ -215,278 +212,290 @@
</template>
<script>
export default {
name: "orderManagement",
props: {
instance: Function,
dict: Object,
permissions: Function,
areaId: String,
},
data() {
return {
searchObj: {
name: "",
orderStatus: "",
createTimeStart: null,
createTimeEnd: null,
shopId: "",
},
page: {
size: 10,
current: 1,
total: 0,
},
tableData: [],
shopList: [],
ids: [],
};
},
computed: {
colConfigs() {
let _ = this;
return [
{slot: "selection"},
{
prop: "orderCode",
align: "center",
slot: "orderCode",
label: "订单号/创建时间",
},
{
prop: "merchandisePhoto",
slot: "merchandisePhoto",
align: "center",
label: "商品图",
},
{
prop: "merchandiseName",
align: "left",
label: "商品名",
width: 180,
"show-overflow-tooltip": false,
},
{
prop: "costIntegral",
align: "center",
label: "单价",
width: 100,
},
{
prop: "merchandiseNumber",
align: "center",
label: "数量",
},
{
prop: "allCostIntegral",
align: "center",
label: "消耗积分",
},
{
prop: "familyName",
align: "center",
label: "兑换家庭",
slot: "familyName",
},
{
prop: "createUserName",
align: "center",
label: "操作人",
slot: "createUserName",
},
{
prop: "orderStatus",
align: "center",
label: "订单状态",
fixed: "right",
slot: "orderStatus",
// render(h, {row}) {
// return h('span', {style: {color: _.dict.getColor('integralOrderStatus', row.orderStatus)}}, _.dict.getLabel('integralOrderStatus', row.orderStatus))
// }
},
];
export default {
name: "orderManagement",
props: {
instance: Function,
dict: Object,
permissions: Function,
areaId: String,
},
data() {
return {
searchObj: {
name: "",
orderStatus: "",
createTimeStart: null,
createTimeEnd: null,
shopId: "",
},
},
created() {
this.getList();
this.dict.load("integralOrderStatus");
this.getShopList();
},
methods: {
onRowClick(row) {
this.ids = row.map(e => e.id)
page: {
size: 10,
current: 1,
total: 0,
},
handleCommand(val) {
if (this.ids.length == 0) {
return this.$message.error("请选择商品")
tableData: [],
shopList: [],
ids: [],
};
},
computed: {
colConfigs() {
let _ = this;
return [
{slot: "selection"},
{
prop: "orderCode",
align: "center",
slot: "orderCode",
label: "订单号/创建时间",
},
{
prop: "merchandisePhoto",
slot: "merchandisePhoto",
align: "center",
label: "商品图",
},
{
prop: "merchandiseName",
align: "left",
label: "商品名",
width: 180,
"show-overflow-tooltip": false,
},
{
prop: "costIntegral",
align: "center",
label: "单价",
width: 100,
},
{
prop: "merchandiseNumber",
align: "center",
label: "数量",
},
{
prop: "allCostIntegral",
align: "center",
label: "消耗积分",
},
{
prop: "familyName",
align: "center",
label: "兑换家庭",
slot: "familyName",
},
{
prop: "createUserName",
align: "center",
label: "操作人",
slot: "createUserName",
},
{
prop: "orderStatus",
align: "center",
label: "订单状态",
fixed: "right",
slot: "orderStatus",
// render(h, {row}) {
// return h('span', {style: {color: _.dict.getColor('integralOrderStatus', row.orderStatus)}}, _.dict.getLabel('integralOrderStatus', row.orderStatus))
// }
},
];
},
},
created() {
this.getList();
this.dict.load("integralOrderStatus");
this.getShopList();
},
methods: {
onRowClick(row) {
this.ids = row.map(e => e.id)
},
handleCommand(val) {
if (this.ids.length == 0) {
return this.$message.error("请选择商品")
}
this.instance.post(`/app/appvillagerintegralshoporder/changeOrderStatus`, null, {
params: {
ids: this.ids.join(","),
status: val
}
}).then(res => {
if (res.code == 0) {
this.$message.success(`批量${val == 1 ? '兑换' : '取消'}成功`)
this.getList()
}
})
},
handlePendingOrder(ids, status) {
let text = status == 1 ? "确认兑换" : "取消订单"
this.$confirm(`是否${text}?`).then(() => {
this.instance.post(`/app/appvillagerintegralshoporder/changeOrderStatus`, null, {
params: {
ids: this.ids.join(","),
status: val
}
params: {ids, status}
}).then(res => {
if (res.code == 0) {
this.$message.success(`批量${val == 1 ? '完成' : '取消'}成功`)
this.$message.success(`${text}成功`)
this.getList()
}
})
},
getList() {
this.instance
.post(`/app/appvillagerintegralshoporder/list`, null, {
params: {
...this.searchObj,
...this.page,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.tableData = res.data.records;
this.tableData.map((e) => {
e.merchandiseName = e.merchandiseList[0].merchandiseName;
e.merchandiseNumber = e.merchandiseList[0].merchandiseNumber;
e.merchandisePhoto = [
{...JSON.parse(e.merchandiseList[0].merchandisePhoto)[0]},
];
e.idForWeb = e.merchandiseList[0].idForWeb;
e.costIntegral = e.merchandiseList[0].costIntegral;
e.allCostIntegral =
Number(e.merchandiseList[0].costIntegral) *
Number(e.merchandiseNumber);
e.merchandiseList.splice(0, 1);
e.isParent = true;
if (e.merchandiseList.length > 0) {
e.merchandiseList.map((e2) => {
e2.createTime = "";
let arr = JSON.parse(e2.merchandisePhoto);
e2.merchandisePhoto = [{...arr[0]}];
e2.allCostIntegral =
Number(e2.costIntegral) * Number(e2.merchandiseNumber);
e2.isParent = false;
// e2.id = e2.orderId
});
}
}).catch(() => 0)
},
getList() {
this.instance.post(`/app/appvillagerintegralshoporder/list`, null, {
params: {
...this.searchObj,
...this.page,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.tableData = res.data.records;
this.tableData.map((e) => {
e.merchandiseName = e.merchandiseList[0].merchandiseName;
e.merchandiseNumber = e.merchandiseList[0].merchandiseNumber;
e.merchandisePhoto = [
{...JSON.parse(e.merchandiseList[0].merchandisePhoto)[0]},
];
e.idForWeb = e.merchandiseList[0].idForWeb;
e.costIntegral = e.merchandiseList[0].costIntegral;
e.allCostIntegral =
Number(e.merchandiseList[0].costIntegral) *
Number(e.merchandiseNumber);
e.merchandiseList.splice(0, 1);
e.isParent = true;
if (e.merchandiseList.length > 0) {
e.merchandiseList.map((e2) => {
e2.createTime = "";
let arr = JSON.parse(e2.merchandisePhoto);
e2.merchandisePhoto = [{...arr[0]}];
e2.allCostIntegral =
Number(e2.costIntegral) * Number(e2.merchandiseNumber);
e2.isParent = false;
// e2.id = e2.orderId
});
this.page.total = res.data.total;
}
});
},
getShopList() {
return new Promise((reslove) => {
this.instance
.post(`/app/appvillagerintegralshop/list`, null, {
params: {
size: 100000,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.shopList = res.data.records;
reslove();
}
});
});
},
reset() {
Object.keys(this.searchObj).forEach((e) => {
this.searchObj[e] = "";
});
this.searchObj.createTimeStart = null;
this.searchObj.createTimeEnd = null;
this.getList();
},
add() {
this.$emit("showDetail", {isAdd: true});
},
goDetail(row) {
console.log(row);
this.$emit("showDetail", {isAdd: false, ...row});
},
finishOrder(row) {
this.$confirm(`是否完成此订单?`, {
type: "error",
})
.then(() => {
this.instance
.post(`/app/appvillagerintegralshoporder/FinishOrder`, null, {
params: {
orderId: row.id,
},
})
.then((res) => {
if (res.code == 0) {
this.$message.success("已完成!");
this.getList();
}
});
})
.catch(() => {
});
},
overOrder(row) {
this.$confirm(`是否结束此订单?`, {
type: "error",
})
.then(() => {
this.instance
.post(`/app/appvillagerintegralshoporder/overOrder`, null, {
params: {
orderId: row.id,
},
})
.then((res) => {
if (res.code == 0) {
this.$message.success("已结束!");
this.getList();
}
});
})
.catch(() => {
});
},
this.page.total = res.data.total;
}
});
},
};
getShopList() {
return new Promise((reslove) => {
this.instance
.post(`/app/appvillagerintegralshop/list`, null, {
params: {
size: 100000,
areaId: this.areaId,
},
})
.then((res) => {
if (res.code == 0) {
this.shopList = res.data.records;
reslove();
}
});
});
},
reset() {
Object.keys(this.searchObj).forEach((e) => {
this.searchObj[e] = "";
});
this.searchObj.createTimeStart = null;
this.searchObj.createTimeEnd = null;
this.getList();
},
add() {
this.$emit("showDetail", {isAdd: true});
},
goDetail(row) {
console.log(row);
this.$emit("showDetail", {isAdd: false, ...row});
},
finishOrder(row) {
this.$confirm(`是否完成此订单?`, {
type: "error",
})
.then(() => {
this.instance
.post(`/app/appvillagerintegralshoporder/FinishOrder`, null, {
params: {
orderId: row.id,
},
})
.then((res) => {
if (res.code == 0) {
this.$message.success("已完成!");
this.getList();
}
});
})
.catch(() => {
});
},
overOrder(row) {
this.$confirm(`是否结束此订单?`, {
type: "error",
})
.then(() => {
this.instance
.post(`/app/appvillagerintegralshoporder/overOrder`, null, {
params: {
orderId: row.id,
},
})
.then((res) => {
if (res.code == 0) {
this.$message.success("已结束!");
this.getList();
}
});
})
.catch(() => {
});
},
},
};
</script>
<style lang="scss" scoped>
.order_management {
height: 100%;
overflow: auto;
background: #f3f6f9;
.order_management {
height: 100%;
overflow: auto;
background: #f3f6f9;
.times_div {
display: flex;
align-items: center;
.times_div {
display: flex;
align-items: center;
.times {
display: block;
width: 72px;
height: 30px;
line-height: 30px;
margin: 0;
text-align: center;
background: #f5f5f5;
border-radius: 2px 0px 0px 2px;
border: 1px solid #d0d4dc;
font-size: 14px;
color: #666666;
}
}
.iconfont {
cursor: pointer;
}
.iconCorrect {
color: #53b43b;
}
.iconReject {
color: #e75555;
padding: 0 8px;
.times {
display: block;
width: 72px;
height: 30px;
line-height: 30px;
margin: 0;
text-align: center;
background: #f5f5f5;
border-radius: 2px 0px 0px 2px;
border: 1px solid #d0d4dc;
font-size: 14px;
color: #666666;
}
}
.iconfont {
cursor: pointer;
}
.iconCorrect {
color: #53b43b;
}
.iconReject {
color: #e75555;
padding: 0 8px;
}
}
</style>

View File

@@ -0,0 +1,36 @@
<template>
<section class="AppScoreSysUser">
<component :is="currentPage" v-bind="$props"/>
</section>
</template>
<script>
import SsuList from "./ssuList";
import SsuDetail from "./ssuDetail";
export default {
name: "AppScoreSysUser",
label: "员工积分",
components: {SsuDetail, SsuList},
props: {
instance: Function,
dict: Object,
permissions: Function
},
computed: {
currentPage() {
return this.$route.query.id ? SsuDetail : SsuList
}
},
created() {
this.dict.load("yesOrNo", "integralGiveObjType")
}
}
</script>
<style lang="scss" scoped>
.AppScoreSysUser {
height: 100%;
}
</style>

View File

@@ -0,0 +1,201 @@
<template>
<section class="ssuDetail">
<ai-detail>
<template slot="title">
<ai-title title="积分明细" isShowBack isShowBottomBorder @onBackClick="$router.push({})"/>
</template>
<template slot="content">
<div class="detail-info">
<div class="detail-info__item">
<h2>姓名</h2>
<span v-text=" detail.sysUserName"/>
</div>
<div class="detail-info__item">
<h2>员工积分</h2>
<el-row type="flex" align="middle">
<span class="color-26f fill" v-text="detail.sysUserIntegral || 0"/>
<el-button type="text" @click="dialog=true,flag=false" v-if="user.info.id==detail.sysUserId">积分赠送</el-button>
</el-row>
</div>
<div class="detail-info__item">
<h2>已用积分</h2>
<span>{{ detail.sysUserUsedIntegral || 0 }}</span>
</div>
</div>
<ai-card title="积分变动明细">
<template slot="right">
<ai-download
:instance="instance"
url="/app/appvillagerintegraldetail/sysUserExport"
:disabled="!Boolean(tableData.length)"
:params="{residentId:detail.sysUserId,type}"
fileName="积分变动明细">
<el-button type="text" icon="iconfont iconExported">导出</el-button>
</ai-download>
</template>
<template #content>
<ai-search-bar>
<template #left>
<ai-select v-model="type" placeholder="请选择类型" @change="page.current=1,getDetail()"
:selectList="dict.getDict('integralDetailType')"/>
</template>
</ai-search-bar>
<ai-table :tableData="tableData" :col-configs="colConfigs" :total="page.total" border :dict="dict" :current.sync="page.current"
:size.sync="page.size" @getList="getDetail"/>
</template>
</ai-card>
</template>
</ai-detail>
<ai-dialog title="积分赠送" width="600px" :visible.sync="dialog" @onConfirm="handleGiveScore" @closed="form={}">
<el-alert type="warning" show-icon title="请注意,确认赠送对象和分值,积分赠送后,不可撤回。" :closable="false"/>
<el-form class="mt10" size="small" ref="DialogForm" label-width="100px" label-suffix="" :rules="rules" :model="form">
<el-form-item label="选择对象" prop="objectType">
<ai-select v-model="form.objectType" :selectList="dict.getDict('integralGiveObjType')" @change="form.userId=null"/>
</el-form-item>
<el-form-item label="选择人员" prop="userId" v-if="form.objectType">
<ai-person-select v-show="form.objectType==1" :instance="instance" url="/admin/user/userIntegralList" customClicker
@selectPerson="handleResidentSelect" headerTitle="员工列表"/>
<ai-person-select v-show="form.objectType==0" :instance="instance" :url="`/app/appresident/list?areaId=${user.info.areaId}`"
@selectPerson="handleResidentSelect" customClicker/>
</el-form-item>
<el-form-item label="赠送分值" prop="integral">
<el-input v-model="form.integral" clearable placeholder="请输入">
<span slot="append">积分总额:{{ detail.sysUserIntegral || 0 }}</span>
</el-input>
</el-form-item>
</el-form>
</ai-dialog>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: 'ssuDetail',
props: {
instance: Function,
dict: Object
},
data() {
return {
page: {current: 1, size: 10, total: 0},
type: "",
detail: {},
tableData: [],
form: {},
dialog: false,
rules: {
integral: {required: true, message: "请输入赠送分值,最多保留一位小数", pattern: /^\d*[.\d]\d?$/},
objectType: {required: true, message: "请选择对象"},
userId: {required: true, message: "请选择人员"},
},
flag: false
}
},
created() {
this.dict.load('integralDetailType')
this.getDetail()
},
computed: {
...mapState(['user']),
colConfigs() {
return [
{prop: 'doTime', label: '时间', width: 200},
{prop: "type", label: "类型", dict: "integralDetailType", align: 'center'},
{
prop: 'changeIntegral', align: 'center', label: '变动积分',
render: (h, {row}) => h('p', `${row.integralCalcType == 1 ? '+' : '-'}${row.changeIntegral}`)
},
{prop: 'nowIntegral', align: 'center', label: '剩余积分'},
{prop: 'eventDesc', label: '事件', width: 500}
]
}
},
methods: {
getDetail() {
let {id: userId} = this.$route.query, {type} = this
this.instance.post('/app/appvillagerintegraldetail/sysUserIntegralList', null, {
params: {userId, ...this.page, type}
}).then(res => {
if (res?.data) {
this.detail = res.data
this.tableData = res.data.details?.records || []
this.page.total = res.data.details?.total || 0
}
})
},
handleGiveScore() {
if(this.flag) return
this.$refs.DialogForm.validate(v => {
if (v) {
this.flag = true
this.instance.post("/admin/user/giveIntegral", null, {
params: {...this.form}
}).then(res => {
if (res?.code == 0) {
this.$message.success("提交成功!")
this.dialog = false
this.getDetail()
}else{
this.flag = false
}
}).catch(() => {
this.flag = false
})
}
})
},
handleResidentSelect(v) {
this.form.userId = v?.id || ""
this.form.userName = v?.name || ""
this.$refs.DialogForm.clearValidate("userId")
}
}
}
</script>
<style lang="scss" scoped>
.ssuDetail {
height: 100%;
.detail-info {
display: flex;
align-items: center;
margin-bottom: 20px;
.detail-info__item {
flex: 1;
height: 96px;
margin-right: 20px;
padding: 16px 24px;
background: #FFFFFF;
box-shadow: 0 4px 6px -2px rgba(15, 15, 21, 0.15);
border-radius: 4px;
&:last-child {
margin-right: 0;
}
h2 {
margin-bottom: 8px;
color: #888888;
font-size: 16px;
font-weight: bold;
}
span {
display: block;
line-height: 32px;
font-size: 24px;
font-weight: bold;
color: #222;
}
}
}
::v-deep.color-26f {
color: #26f !important;
}
}
</style>

View File

@@ -0,0 +1,112 @@
<template>
<section class="ssuList">
<ai-list>
<template slot="title">
<ai-title title="员工积分" isShowBottomBorder/>
</template>
<template slot="content">
<ai-search-bar bottomBorder>
<template slot="left">
<ai-select v-model="searchObj.integralNotEmpty" placeholder="积分是否大于0" :selectList="dict.getDict('yesOrNo')"
@change="page.current = 1,getList()"/>
</template>
<template slot="right">
<el-input v-model="searchObj.con" size="small" placeholder="姓名、联系方式" @change="page.current=1,getList()"
clearable suffix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
<ai-search-bar class="mt10">
<template slot="left">
<ai-download :instance="instance" type="primary" url="/admin/user/exportUserIntegralList" :params="searchObj" fileName="员工积分"></ai-download>
</template>
</ai-search-bar>
<ai-table :tableData="tableData" :col-configs="colConfigs" :total="page.total" :current.sync="page.current" :size.sync="page.size" :dict="dict"
@getList="getList">
<el-table-column label="操作" slot="options" fixed="right" align="center" width="180">
<template v-slot="{row}">
<div class="table-options">
<el-button type="text" :disabled="!permissions('app_appvillagerintegralfamily_detail')" title="详情" @click="goDetail(row)">详情</el-button>
</div>
</template>
</el-table-column>
</ai-table>
</template>
</ai-list>
</section>
</template>
<script>
import {mapState} from 'vuex';
export default {
name: 'ssuList',
props: {
instance: Function,
dict: Object,
permissions: Function
},
data() {
return {
searchObj: {},
page: {
current: 1,
size: 10,
total: 0
},
tableData: [],
}
},
computed: {
...mapState(['user']),
colConfigs() {
return [
{prop: 'name', label: '姓名'},
{prop: 'phone', label: '联系电话', align: 'center'},
{prop: 'areaName', align: 'center', label: '所在区域'},
{prop: 'integral', align: 'center', label: '员工积分'},
{prop: 'usedIntegral', align: 'center', label: '已用积分'},
]
},
},
created() {
this.getList();
},
methods: {
getList() {
this.instance.post("/admin/user/userIntegralList", null, {
params: {
...this.searchObj,
...this.page,
}
}).then(res => {
if (res?.data) {
this.tableData = res.data.records
this.page.total = res.data.total
}
})
},
goDetail(row) {
let {id} = row
this.$router.push({query: {id}})
}
}
}
</script>
<style lang="scss" scoped>
.ssuList {
height: 100%;
background: #f3f6f9;
overflow: auto;
.iconfont {
cursor: pointer;
}
.family-list {
::v-deep .el-table--small {
font-size: 14px !important;
}
}
}
</style>

View File

@@ -9,6 +9,7 @@
<script>
import List from './components/List'
import Add from './components/Add'
import Detail from './components/Detail'
export default {
label: '播发记录',
@@ -28,7 +29,8 @@ export default {
components: {
Add,
List
List,
Detail
},
methods: {
onChange(data) {
@@ -37,6 +39,11 @@ export default {
this.params = data.params
}
if (data.type === 'detail') {
this.component = 'Detail'
this.params = data.params
}
if (data.type == 'list') {
this.component = 'List'
this.params = data.params

View File

@@ -0,0 +1,121 @@
<template>
<ai-detail isHasSidebar class="Detail">
<template slot="title">
<ai-title title="任务详情" isShowBack isShowBottomBorder @onBackClick="cancel(true)">
</ai-title>
</template>
<template slot="content">
<AiSidebar :tabTitle="tabList" v-model="currIndex"></AiSidebar>
<div v-show="currIndex == 0">
<ai-card title="播发任务" v-show="currIndex === 0">
<template #content>
<ai-wrapper
label-width="120px">
<ai-info-item label="播发级别" v-show="info.taskType == 0">{{ $dict.getLabel('dlbMessageUrgency', info.messageLevel) }}</ai-info-item>
<ai-info-item label="播发级别" v-show="info.taskType == 1">{{ $dict.getLabel('dlbMessageUrgency', info.messageLevel) }} - {{ $dict.getLabel('dlbDyclingType', info.cyclingType) }}</ai-info-item>
<ai-info-item label="播放方式" :value="info.taskType == 1? '定时播放':'立即播放'"></ai-info-item>
<ai-info-item label="创建人" :value="info.createUserName"></ai-info-item>
<ai-info-item label="创建时间" :value="info.createTime"></ai-info-item>
<ai-info-item label="开始日期" :value="info.startDate" v-if="info.taskType == 1"></ai-info-item>
<ai-info-item label="播放天数" :value="info.broadcastDay" v-if="info.cyclingType == 3 && info.taskType == 1"></ai-info-item>
<ai-info-item label="播放天数" v-if="info.cyclingType == 2 && info.taskType == 1">
<span v-for="(item, index) in info.cyclingDateList" :key="index"><span v-if="index > 0">,</span>{{dayList[item]}}</span>
</ai-info-item>
<ai-info-item label="开始时间" :value="info.startTime" v-if="info.taskType == 1"></ai-info-item>
<ai-info-item label="结束时间" :value="info.endTime" v-if="info.taskType == 1"></ai-info-item>
</ai-wrapper>
</template>
</ai-card>
</div>
<ai-card title="播发设备" v-show="currIndex == 1">
<template #right>
<div style="color: #333;font-size: 15px;"><span style="color: #0082ff;font-size: 15px;" v-if="info.devices">{{info.devices.length}}</span>个设备</div>
</template>
<template #content>
<ai-table
class="detail-table__table"
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
:isShowPagination="false"
@getList="getDetail">
</ai-table>
</template>
</ai-card>
<ai-card title="播发素材" v-show="currIndex == 2">
<template #content>
<div class="audios">
<!-- <div>{{item.}}</div> -->
<ai-audio :src="item.url" v-for="item in info.materials" :key="item.id" skin="flat" style="margin-bottom: 8px;"/>
</div>
</template>
</ai-card>
</template>
</ai-detail>
</template>
<script>
export default {
name: 'Detail',
components: {},
props: {
dict: Object,
params: Object,
instance: Function,
},
data() {
return {
tabList: ['播发任务','播发设备','播发素材'],
currIndex: 0,
info: {},
tableData: [],
search: {},
total: 0,
colConfigs: [
{prop: 'name', label: '设备名称', width: 400},
{prop: 'areaName', label: '行政区划', align: 'center'},
{prop: 'devStatus', label: '状态', align: 'center', render: (h, { row })=>{
return h('span',null,this.dict.getLabel('dlbDevStatus',row.devStatus))
}},
],
dayList: ['', '每周一', '每周二', '每周三', '每周四', '每周五', '每周六', '每周日'],
voiceList: [],
}
},
created() {
this.$dict.load('dlbMessageUrgency','dlbDyclingType','dlbDevStatus').then(()=>{
if(this.params.id) {
this.getDetail()
}
})
},
methods: {
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh,
})
},
getDetail() {
this.instance.post(`/app/appzyvideobroadcast/queryDetailById?id=${this.params.id}`).then((res) => {
if(res?.data) {
this.info = res.data
this.tableData = res.data.devices
this.total = res.data.devices.length
if(this.info.cyclingType == 2) {
this.info.cyclingDateList = this.info.cyclingDate.split(',')
}
}
})
},
}
}
</script>
<style lang="scss" scoped>
.Detail {
height: 100%;
}
</style>

View File

@@ -5,15 +5,15 @@
<template #content>
<ai-search-bar bottomBorder>
<template slot="left">
<ai-select v-model="search.messageType" placeholder="媒资类型" clearable
<ai-select v-model="search.type" placeholder="媒资类型" clearable
:selectList="$dict.getDict('dlbResourceType')"
@change=";(page.current = 1), getList()"></ai-select>
<ai-select v-model="search.messageUrgency" placeholder="级别" clearable
<ai-select v-model="search.messageLevel" placeholder="级别" clearable
:selectList="$dict.getDict('dlbMessageUrgency')"
@change=";(page.current = 1), getList()"></ai-select>
</template>
<template slot="right">
<el-input v-model="search.messageName" size="small" placeholder="媒资名称" clearable
<el-input v-model="search.sourceName" size="small" placeholder="媒资名称" clearable
v-throttle="() => {page.current = 1, getList()}"
@clear=";(page.current = 1), (search.messageName = ''), getList()"
suffix-icon="iconfont iconSearch"/>
@@ -25,14 +25,15 @@
<!-- <el-button icon="iconfont iconDelete" size="small" @click="removeAll" :disabled="ids.length == 0">删除 </el-button> -->
</template>
</ai-search-bar>
<ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" :dict="dict"
<ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" :dict="dict" v-loading="loading"
:current.sync="page.current" :size.sync="page.size" @getList="getList"
@selection-change="(v) => (ids = v.map((e) => e.id))">
<el-table-column slot="options" label="操作" align="center" width="180" fixed="right">
<template slot-scope="{ row }">
<el-button type="text" @click="onAdd(row.broadcastId)">复制</el-button>
<el-button type="text" @click="cancel(row.broadcastId)"
v-if="row.broadcastStatus == 0 || row.broadcastStatus == 1 || row.broadcastStatus == 2">撤回
<!-- <el-button type="text" @click="onAdd(row.id)">复制</el-button> -->
<el-button type="text" @click="toDetail(row.id)">详情</el-button>
<el-button type="text" @click="reset(row.id)"
v-if="row.taskType == 1 && (row.broadcastStatus == 0 || row.broadcastStatus == 1 || row.broadcastStatus == 2 )">撤回
</el-button>
</template>
</el-table-column>
@@ -62,25 +63,34 @@ export default {
},
total: 0,
search: {
messageName: '',
messageType: '',
messageUrgency: '',
sourceName: '',
cyclingType: '',
messageLevel: '',
},
id: '',
ids: [],
colConfigs: [
{prop: 'messageName', label: '媒资名称', width: 400},
{prop: 'messageType', label: '媒资类型', align: 'center', dict: "dlbResourceType"},
{prop: 'messageUrgency', label: '级别', align: 'center', dict: "dlbMessageUrgency"},
{prop: 'taskType', label: '播发方式', align: 'center', dict: "dlbBroadTaskType"},
{prop: 'startDate', label: '开始时间', align: 'center', width: 180},
{prop: 'broadcastStatus', label: '状态', align: 'center', dict: "dlbBroadcastStatus"},
{prop: 'areaName', label: '地区', align: 'center'},
{prop: 'sourceName', label: '媒资名称', width: 200},
{prop: 'type', label: '媒资类型', align: 'center', render: (h, {row}) => {
return h('span', null, this.dict.getLabel('dlbResourceType',row.type))},
},
{prop: 'messageLevel', label: '级别', align: 'center', dict: "dlbMessageUrgency"},
{prop: 'taskType', label: '播发方式', align: 'center', render: (h, {row}) => {
return h('span', null, (row.taskType == 1? '定时播放':'立即播放'))},
},
{prop: 'startTime', label: '开始时间', align: 'center', width: 180},
{prop: 'broadcastStatus', label: '状态', align: 'center',
render: (h, { row })=>{
return h('span',null, (row.broadcastStatus == 0? '已下发': row.broadcastStatus == 3? '播发成功': row.broadcastStatus == 6? '已取消': ''))
}
},
// {prop: 'areaName', label: '地区', align: 'center'},
{prop: 'createUserName', label: '创建人', align: 'center'},
{slot: 'options'},
],
tableData: [],
areaId: '',
loading: false,
}
},
@@ -98,14 +108,15 @@ export default {
created() {
this.areaId = this.user.info.areaId
this.dict.load('dlbResourceType', 'dlbMessageUrgency', 'dlbBroadTaskType', 'dlbBroadcastStatus', 'dlbMessageUrgency').then(() => {
this.dict.load('dlbDyclingType', 'dlbMessageUrgency', 'dlbBroadTaskType', 'dlbBroadcastStatus', 'dlbMessageUrgency').then(() => {
this.getList()
this.loading = true
})
},
methods: {
getList() {
this.instance.post(`/app/appzyvideobroadcast/getBroadcastRecords`, null, {
this.instance.post(`/app/appzyvideobroadcast/list`, null, {
params: {
...this.page,
...this.search,
@@ -115,7 +126,10 @@ export default {
if (res.code == 0) {
this.tableData = res.data.records
this.total = parseInt(res.data.total)
this.loading = false
}
}).catch(() => {
this.loading = false
})
},
onAdd(id) {
@@ -126,8 +140,16 @@ export default {
}
})
},
cancel(id) {
this.$confirm('确定撤回该广播?').then(() => {
toDetail(id) {
this.$emit('change', {
type: 'detail',
params: {
id: id || ''
}
})
},
reset(id) {
this.$confirm('确定要撤回该广播?').then(() => {
this.instance.post(`/app/appzyvideobroadcast/getBroadcastRecall?broadcastId=${id}`).then((res) => {
if (res.code == 0) {
this.$message.success('撤回成功!')

View File

@@ -8,6 +8,7 @@
<script>
import List from './components/List'
import taskList from './components/taskList'
export default {
label: '广播设备管理',
@@ -26,12 +27,13 @@ export default {
},
components: {
List
List,
taskList,
},
methods: {
onChange(data) {
if (data.type === 'add') {
this.component = 'Add'
if (data.type === 'taskList') {
this.component = 'taskList'
this.params = data.params
}

View File

@@ -4,16 +4,13 @@
<ai-title slot="title" title="广播设备管理" isShowBottomBorder/>
<template #content>
<ai-search-bar bottomBorder>
<template slot="right">
<el-input v-model="search.keyword" size="small" placeholder="设备名称/设备编号" clearable
v-throttle="() => {page.current = 1, getList()}"
@clear=";(page.current = 1), (search.keyword = ''), getList()" suffix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
<ai-search-bar class="ai-search-ba mar-t10">
<template slot="left">
<!-- <el-button icon="iconfont" type="primary" size="small">数据同步</el-button> -->
<!-- <el-button icon="iconfont iconDelete" size="small" @click="removeAll" :disabled="ids.length == 0">删除 </el-button> -->
<el-button type="primary" icon="iconfont iconResetting" @click="update" :loading="btnLoading">更新数据</el-button>
</template>
<template slot="right">
<el-input v-model="search.name" size="small" placeholder="设备名称/设备编号" clearable
v-throttle="() => {page.current = 1, getList()}"
@clear=";(page.current = 1), (search.name = ''), getList()" suffix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
<ai-table :tableData="tableData" :col-configs="colConfigs" :total="total" ref="aitableex"
@@ -21,9 +18,10 @@
@selection-change="(v) => (ids = v.map((e) => e.id))">
<el-table-column slot="options" label="操作" align="center" width="280" fixed="right">
<template slot-scope="{ row }">
<el-button type="text" @click="close(row.id)">停播</el-button>
<el-button type="text" @click="bind(row)">绑定行政区划</el-button>
<!-- <el-button type="text" @click="locate=true">地图标绘</el-button>-->
<!-- <el-button type="text" @click="close(row.id)">停播</el-button> -->
<el-button type="text" @click="toTaskList(row.deviceId)">任务列表</el-button>
<el-button type="text" @click="bind(row)" >绑定行政区划</el-button>
<!-- <el-button type="text" @click="locate=true">地图标绘</el-button>-->
</template>
</el-table-column>
</ai-table>
@@ -65,20 +63,21 @@ export default {
},
total: 0,
search: {
bind: '',
keyword: '',
name: '',
},
id: '',
ids: [],
colConfigs: [
{
prop: 'deviceName',
prop: 'name',
label: '设备名称',
width: '200',
},
{
prop: 'areaName',
label: '所属行政区划',
align: 'center',
width: '200',
},
{
prop: 'serialNo',
@@ -88,7 +87,7 @@ export default {
{
prop: 'devStatus',
label: '设备状态',
width: '100',
width: '200',
align: 'center',
render: (h, {row}) => {
return h('span', null, this.dict.getLabel('dlbDevStatus', row.devStatus))
@@ -97,10 +96,9 @@ export default {
{
prop: 'bind',
label: '是否绑定区划',
width: '120',
align: 'center',
render: (h, {row}) => {
return h('span', null, this.dict.getLabel('yesOrNo', row.bind))
return h('span', null, (row.areaId? '是': '否'))
},
},
{
@@ -113,6 +111,7 @@ export default {
areaId: '',
bindVisible: false,
changeInfo: {},
btnLoading: false,
locate: false
}
},
@@ -174,7 +173,7 @@ export default {
})
},
getList() {
this.instance.post(`/app/appdlbquipment/getDlbDeviceList`, null, {
this.instance.post(`/app/appdlbquipment/list`, null, {
params: {
...this.page,
...this.search,
@@ -187,6 +186,32 @@ export default {
}
})
},
toTaskList(id) {
this.$emit('change', {
type: 'taskList',
params: {
id: id || '',
// areaId: this.areaId,
},
})
},
update () {
this.btnLoading = true
this.instance.post(`/app/appdlbquipment/sync`, null, {
timeout: 1000000
}).then(res => {
if (res.code == 0) {
this.$message.success('更新成功')
this.getList()
}
this.btnLoading = false
}).catch(() => {
this.btnLoading = false
})
},
},
}
</script>

View File

@@ -0,0 +1,151 @@
<template>
<section class="taskList">
<ai-list>
<ai-title slot="title" title="任务列表" isShowBack isShowBottomBorder @onBackClick="cancel(true)"/>
<template #content>
<ai-search-bar bottomBorder>
<template slot="right">
<el-input v-model="search.sourceName" size="small" placeholder="媒资名称/创建人" clearable
v-throttle="() => {page.current = 1, getList()}"
@clear=";(page.current = 1), (search.sourceName = ''), getList()" suffix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
<ai-table :tableData="tableData" :col-configs="colConfigs" :total="page.total" ref="aitableex"
:current.sync="page.current" :size.sync="page.size" @getList="getList"
@selection-change="(v) => (ids = v.map((e) => e.id))">
<el-table-column slot="options" label="操作" align="center" width="280" fixed="right">
<template slot-scope="{ row }" v-if="row.taskType == 1 && (row.broadcastStatus == 0 || row.broadcastStatus == 1 || row.broadcastStatus == 2 )">
<el-button type="text" @click="reset(row.id)">撤回任务</el-button>
</template>
</el-table-column>
</ai-table>
</template>
</ai-list>
</section>
</template>
<script>
export default {
name: 'taskList',
components: {},
props: {
dict: Object,
instance: Function,
params: Object,
},
data() {
return {
page: {
current: 1,
size: 10,
total: 0,
},
search: {
sourceName: '',
},
tableData: [],
colConfigs: [
{
prop: 'sourceName',
label: '任务名称',
},
{
prop: 'type',
label: '媒资类型',
width: '200',
align: 'center',
render: (h, { row })=>{
return h('span',null,this.dict.getLabel('dlbResourceType',row.type))
}
},
{
prop: 'messageLevel',
label: '级别',
align: 'center',
render: (h, { row })=>{
return h('span',null,this.dict.getLabel('dlbMessageUrgency',row.messageLevel))
}
},
{
prop: 'taskType',
label: '播发方式',
width: '220',
align: 'center',
render: (h, {row}) => {
return h('span', null, (row.taskType == 1? '定时播放':'立即播放'))
},
},
{
prop: 'startTime',
label: '开始时间',
width: '120',
align: 'center',
},
{
prop: 'broadcastStatus',
label: '状态',
align: 'center',
render: (h, { row })=>{
return h('span',null, (row.broadcastStatus == 0? '已下发': row.broadcastStatus == 3? '播发成功': row.broadcastStatus == 6? '已取消': ''))
}
},
{
prop: 'createUserName',
label: '创建人',
align: 'center',
},
{
slot: 'options',
label: '操作',
align: 'center',
},
],
}
},
created() {
this.$dict.load('dlbDyclingType','dlbMessageUrgency','dlbBroadcastStatus','dlbResourceType').then(()=>{
this.getList()
})
},
methods: {
getList() {
this.instance.post(`/app/appzyvideobroadcast/list?deviceId`,null,{
params: {
...this.page,
...this.search,
deviceId: this.params.deviceId
}
}).then(res=>{
if(res?.data) {
this.tableData = res.data.records
this.page.total = res.data.total
}
})
},
reset(id) {
this.$confirm('确定要撤回该任务吗?').then(() => {
this.instance.post(`/app/appzyvideobroadcast/getBroadcastRecall?broadcastId=${id}`).then((res) => {
if (res.code == 0) {
this.$message.success('撤回成功!')
this.getList()
}
})
})
},
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh,
})
},
},
}
</script>
<style lang="scss" scoped>
.taskList {
height: 100%;
}
</style>

View File

@@ -32,13 +32,46 @@
</el-table-column>
<el-table-column slot="options" label="操作" align="center" width="180" fixed="right">
<div class="table-options" slot-scope="{ row }">
<el-button type="text" @click="play(row.id)">播发</el-button>
<!-- play(row.id) -->
<el-button type="text" @click="getItemInfo(row.id)">播发</el-button>
<el-button type="text" @click="remove(row.id)">删除</el-button>
</div>
</el-table-column>
</ai-table>
</template>
</ai-list>
<ai-dialog
title="广播播发"
:visible.sync="detailDialog"
:customFooter="true"
:destroyOnClose="true"
width="780px">
<ai-detail style="background: #FFF;">
<template #content>
<div class="audios">
<ai-audio :src="info.url" skin="flat"/>
</div>
<ai-wrapper style="margin-top: 30px;">
<ai-info-item label="媒资名称" :value="info.name"></ai-info-item>
<!-- <ai-info-item label="状态">{{ $dict.getLabel('dlbDevStatus', info.devStatus) }}</ai-info-item> -->
<ai-info-item label="媒资类型">{{$dict.getLabel('dlbResourceType', info.type)}}</ai-info-item>
<ai-info-item label="创建时间" :value="info.createTime"></ai-info-item>
<ai-info-item label="内容" class="contentBox" v-if="info.type == 3" isLine>
<div class="content">
{{ info.content }}
</div>
</ai-info-item>
</ai-wrapper>
</template>
</ai-detail>
<div class="dialog-footer" slot="footer">
<el-button @click="detailDialog=false" size="medium">关闭</el-button>
<el-button @click="play(info.id)" type="primary" size="medium">新建广播</el-button>
</div>
</ai-dialog>
</section>
</template>
@@ -82,9 +115,9 @@ export default {
return h('span', null, this.dict.getLabel('dlbResourceType', row.type))
},
},
{
slot: 'content',
},
// {
// slot: 'content',
// },
{prop: 'createTime', label: '创建时间', align: 'center'},
{
prop: 'createUserName',
@@ -101,6 +134,8 @@ export default {
],
tableData: [],
areaId: '',
detailDialog: false,
info: {},
}
},
@@ -115,15 +150,14 @@ export default {
},
},
created() {
this.dict.load('dlbResourceType').then(() => {
this.dict.load('dlbResourceType','dlbDevStatus').then(() => {
this.getList()
})
},
methods: {
getList() {
this.instance
.post(`/app/appdlbresource/list`, null, {
this.instance.post(`/app/appdlbresource/list`, null, {
params: {
...this.page,
...this.search,
@@ -137,7 +171,17 @@ export default {
})
},
getItemInfo (id) {
this.instance.post(`/app/appdlbresource/queryDetailById?id=${id}`).then(res => {
if (res?.data) {
this.info = res.data
this.detailDialog = true
}
})
},
play (id) {
this.detailDialog = false
this.$emit('change', {
type: 'Play',
params: {
@@ -184,5 +228,18 @@ export default {
.mar-t10 {
margin-top: 10px;
}
.audios {
padding-left: 40px;
}
::v-deep .ai-info-item__right {
width: 100%;
}
.content {
width: 100%;
height: 200px;
overflow-y: auto;
}
}
</style>

View File

@@ -1,23 +1,23 @@
<template>
<ai-detail>
<ai-detail class="Play">
<template #title>
<ai-title title="添加广播" isShowBack isShowBottomBorder @onBackClick="cancel(false)"></ai-title>
</template>
<template #content>
<ai-card title="基础信息">
<template #content>
<el-alert title="温馨提示:请先选择行政区划,再选择播放设备!" type="warning" show-icon :closable="false" style="margin-bottom: 12px;padding: 4px 20px;"></el-alert>
<el-form class="ai-form" :model="formData" :rules="formRules" ref="ruleForm" label-width="120px">
<el-form-item label="播发内容" prop="mediaId">
<ai-select v-model="formData.mediaId" placeholder="播发内容" clearable :selectList="mediaList"></ai-select>
</el-form-item>
<el-form-item label="播放设备" prop="serialNo">
<ai-select v-model="formData.serialNo" placeholder="播放设备" clearable
:selectList="equipmentList"></ai-select>
</el-form-item>
<el-form-item label="播发级别" prop="messageLevel">
<ai-select v-model="formData.messageLevel" placeholder="播发级别" clearable
:selectList="$dict.getDict('dlbMessageUrgency')"></ai-select>
</el-form-item>
<el-form-item label="设备行政区划">
<ai-area-get v-model="areaId" :root="areaRootId" :instance="instance" @select="handleAreaSelect" size="small" placeholder="请选择行政区划"/>
</el-form-item>
<el-form-item label="播放方式" prop="taskType" class="buildingTypes">
<el-radio-group v-model="formData.taskType">
<el-radio label="0">立即播放</el-radio>
@@ -58,6 +58,10 @@
:picker-options="{ start: formData.startTime, minTime: formData.startTime}"
value-format="HH:mm:ss"></el-time-picker>
</el-form-item>
<el-form-item label="播放设备" v-if="areaId" prop="serialNo" style="width: 100%;">
<ai-table-select nodeName="name" :instance="instance" extra="serialNo" searchKey="name" :action="`/app/appdlbquipment/list?devStatus=5&areaId=${areaId}`"
@select="v => formData.serialNo = v.map(e=> e.serialNo).toString()" multiple/>
</el-form-item>
</el-form>
</template>
</ai-card>
@@ -123,6 +127,9 @@ export default {
mediaId: [
{required: true, message: '请选择播发内容', trigger: 'change'}
],
areaId: [
{required: true, message: '请选择行政区划', trigger: 'change'}
],
serialNo: [
{required: true, message: '请选择播放设备', trigger: 'change'}
],
@@ -151,8 +158,20 @@ export default {
{required: true, message: '播放天数', trigger: 'change'}
],
},
areaRootId: '',
mediaList: [],
equipmentList: []
equipmentList: [],
detailDialog: false,
isAll: false,
input3: '',
defaultProps: {
children: 'children',
label: 'label'
},
serialNoList: [],
areaId: '',
areaName: '',
userAreaId: '',
}
},
computed: {
@@ -166,13 +185,26 @@ export default {
return myDate.getHours() + ':' + myDate.getMinutes() + ':' + myDate.getSeconds()
}
},
watch: {
userAreaId: {
handler: function(v) {
this.areaRootId = [v?.substr(0,6),'000000'].join("")
},
deep: true
}
},
created() {
this.dict.load('dlbMessageUrgency', 'dlbBroadTaskType', 'dlbDyclingType')
Promise.all([this.getEquipmentList(), this.getMediaList()]).then(() => {
this.formData.mediaId = this.params.id
this.userAreaId = this.user.info.areaId
})
},
methods: {
// 选择设备
getSelect() {},
getMediaList() {
return this.instance.post(`/app/appdlbresource/list?current=1&size=10000`).then((res) => {
if (res?.data) {
@@ -193,7 +225,16 @@ export default {
}
})
},
// 地区选择
handleAreaSelect(v) {
this.areaName = v?.[0]?.label
},
// 播放
confirm() {
if(!this.areaId) {
this.$message.error('请选择所要播放设备的行政区划!')
}
this.$refs['ruleForm'].validate((valid) => {
if (valid) {
if (this.formData.checkList.length) {
@@ -250,5 +291,52 @@ export default {
</script>
<style lang="scss" scoped>
.Play {
.equipment {
position: relative;
.select {
position: absolute;
right: 0;
top: 0;
}
}
.equipments {
display: flex;
width: 100%;
height: 32px;
align-items: center;
border-radius: 4px;
border: 1px solid #DDD;
justify-content: space-between;
}
.container {
display: flex;
width: 100%;
height: 100%;
.item {
flex: 1;
display: inline-block;
height: auto;
border: 1px solid #DDD;
.title {
display: flex;
justify-content: space-between;
padding: 10px;
box-sizing: border-box;
height: 50px;
align-items: center;
border-bottom: 1px solid #DDD;
.checkBox {
align-self: center;
}
}
.content {
padding: 10px;
box-sizing: border-box;
}
}
}
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<section class="AppISManage">
<device-slider :permissions="permissions" :show.sync="slider" :ins="instance" :dict="dict" @treeCommand="handleSliderOption" @select="handleSelectMonitor" :render-item="renderTreeItem" ref="DeviceSlider" />
<device-slider :permissions="permissions" :show.sync="slider" :instance="instance" :dict="dict" @treeCommand="handleSliderOption" @select="handleSelectMonitor" :render-item="renderTreeItem" ref="DeviceSlider" />
<div class="monitorPane" v-loading="isLoading" element-loading-background="rgba(0, 0, 0, 0.6)">
<div class="headerBar">
<el-select default-first-option size="small" v-model="splitScreen" @change="onChange">
@@ -54,8 +54,7 @@
splitOps() {
return [
{ label: '单分屏', value: 1, per: '100%' },
{ label: '四分屏', value: 4, per: '49.2%' },
{ label: '九分屏', value: 9, per: '32%' },
{ label: '四分屏', value: 4, per: '49.2%' }
]
},
currentSplitStyle() {

View File

@@ -1,6 +1,6 @@
<template>
<section class="AppISMap">
<device-slider :show.sync="slider" :ins="instance" :dict="dict" @list="v=>list=v" @select="markerClickEvent"/>
<device-slider :show.sync="slider" :instance="instance" :dict="dict" @list="v=>list=v" @select="markerClickEvent"/>
<div id="amap"/>
<div ref="selectedInfoWin" class="selected">
<b>{{ selected.deviceName }}</b>

View File

@@ -22,7 +22,10 @@
prefix-icon="el-icon-search"
@clear="search.name = '', handleTreeFilter()" clearable/>
</div>
<div title>设备列表</div>
<div title>
<div>设备列表</div>
<el-button type="text" icon="iconfont iconResetting" @click="updateDev" size="mini" :loading="btnLoading">刷新</el-button>
</div>
<div fill class="deviceList">
<el-tree ref="deviceTree" highlight-current :render-content="renderItem" :data="treeData" :props="propsConfig"
@node-click="handleNodeClick" @node-contextmenu="nodeContextmenu"
@@ -48,10 +51,10 @@ export default {
name: "deviceSlider",
props: {
show: Boolean,
ins: Function,
instance: Function,
dict: Object,
permissions: Function,
renderItem: Function
renderItem: Function,
},
computed: {
overview() {
@@ -98,7 +101,8 @@ export default {
x: '',
y: '',
node: {}
}
},
btnLoading: false,
}
},
methods: {
@@ -110,8 +114,10 @@ export default {
this.isShowMenu = false
},
getDevices() {
this.ins.post("/app/appzyvideoequipment/tree", null, {
params: {size: 999}
this.instance.post(`/app/appzyvideoequipment/tree`, null, {
params: {
size: 999
}
}).then(res => {
if (res?.data) {
this.staData = res.data.count
@@ -122,6 +128,21 @@ export default {
})
},
updateDev() {
this.btnLoading = true
this.instance.post(`/app/appzyvideoequipment/sync`, null, {
timeout: 1000000
}).then(res => {
if (res.code == 0) {
this.$message.success('更新成功')
this.getDevices()
}
this.btnLoading = false
}).catch(() => {
this.btnLoading = false
})
},
handleTreeCommand(e, node) {
this.$emit('treeCommand', {
type: e,
@@ -154,14 +175,16 @@ export default {
handleTreeFilter() {
this.$refs.deviceTree?.filter(this.search.name)
},
onChange() {
this.$refs.deviceTree?.filter(this.search.name)
}
},
},
created() {
this.dict.load("deviceStatus")
this.getDevices()
this.$dict.load("deviceStatus").then(()=>{
this.getDevices()
})
},
mounted() {
@@ -247,6 +270,18 @@ export default {
background: #3E4A69;
padding: 0 16px;
line-height: 28px;
display: flex;
justify-content: space-between;
align-items: center;
::v-deep .el-button {
padding: 0 4px;
height: 28px;
background: #3E4A69;
}
::v-deep .el-button:hover {
border: none;
}
}
::v-deep.deviceList {
@@ -278,8 +313,8 @@ export default {
.el-tree-node__content {
background: transparent!important;
}
.el-tree-node__children .is-current .el-tree-node__content {
.el-tree-node__children .is-current > .el-tree-node__content {
background: linear-gradient(90deg, #299FFF 0%, #0C61FF 100%)!important;
}

View File

@@ -50,7 +50,7 @@
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="toAdd(row.id)">编辑</el-button>
<el-button type="text" @click="$router.push({name: '监护地图', query: {id: row.id, lat: row.lat, lng: row.lng}})">地图查看</el-button>
<el-button type="text" @click="$router.push({name: '12ed7dcf13014bf0b2bbffa7d0238e0b', query: {id: row.id, lat: row.lat, lng: row.lng}})">地图查看</el-button>
<el-button type="text" @click="toMonitor(row.id)">监测数据</el-button>
<el-button type="text" @click="remove(row.id)">删除</el-button>
</div>

View File

@@ -4,7 +4,7 @@
<ai-title :title="id ? '编辑成员' : '添加成员'" isShowBack isShowBottomBorder @onBackClick="cancel(false)">
</ai-title>
</template>
<template slot="content">
<template slot="content">
<el-form ref="form" :model="form" label-width="110px" label-position="right">
<ai-card title="个人信息">
<template #content>

View File

@@ -13,7 +13,8 @@
<el-form-item :label="item.fieldName" :prop="item.fieldDbName" style="width: 100%">
<!-- 字典下拉选择 -->
<template v-if="item.type == 'dict'">
<ai-select v-model="formData[item.fieldDbName]" :placeholder="item.fieldName" :selectList="dict.getDict(item.dict)" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" />
<ai-select v-model="formData[item.fieldDbName]" :placeholder="item.fieldName" :selectList="dict.getDict(item.dict)"
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"/>
</template>
<!-- 单选radio -->
<template v-else-if="item.type == 'radio'">
@@ -23,7 +24,8 @@
</template>
<!-- 开关onOff -->
<template v-else-if="item.type == 'onOff'">
<el-switch v-model="formData[item.fieldDbName]" active-color="#26f" inactive-color="#ddd" active-value="1" inactive-value="0" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"></el-switch>
<el-switch v-model="formData[item.fieldDbName]" active-color="#26f" inactive-color="#ddd" active-value="1" inactive-value="0"
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"></el-switch>
</template>
<!-- 多选checkbox -->
<template v-else-if="item.type == 'checkbox'">
@@ -37,20 +39,23 @@
<template v-else-if="item.type === 'gird'">
<el-input disabled :value="girdName" size="small" placeholder="请选择网格">
<template slot="append">
<el-button size="small" @click="showGrid = true, treeObj.checkedKeys = formData[item.fieldDbName] ? [formData[item.fieldDbName]] : [], gridFieldName = item.fieldDbName">选择网格</el-button>
<el-button size="small"
@click="showGrid = true, treeObj.checkedKeys = formData[item.fieldDbName] ? [formData[item.fieldDbName]] : [], gridFieldName = item.fieldDbName">
选择网格
</el-button>
</template>
</el-input>
</template>
<template v-else-if="item.type === 'resident'">
<el-input
v-model="formData.name"
:placeholder="'请选择'+item.fieldName">
v-model="formData.name"
:placeholder="'请选择'+item.fieldName">
<template slot="append">
<ai-person-select
:instance="instance"
:disabled="!!params.id"
:url="'/app/appresident/list?auditType=1&areaId=' + user.info.areaId"
:isMultiple="false" dialogTitle="选择" @selectPerson="onChange">
:instance="instance"
:disabled="!!params.id"
:url="'/app/appresident/list?auditType=1&areaId=' + user.info.areaId"
:isMultiple="false" dialogTitle="选择" @selectPerson="onChange">
<template name="option" v-slot:option="{ item }">
<span class="iconfont iconProlife">{{ item.name }}</span>
<ai-id mode="show" :show-eyes="false" :value="item.idNumber"/>
@@ -60,35 +65,42 @@
</el-input>
</template>
<template v-else-if="item.type == 'idNumber'">
<ai-id v-model="formData[item.fieldDbName]" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" />
<ai-id v-model="formData[item.fieldDbName]" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"/>
</template>
<!-- input输入框 -->
<template v-else-if="item.type == 'input' || item.type == 'name' || item.type == 'phone'">
<el-input v-model="formData[item.fieldDbName]" :placeholder="'请输入'+item.fieldName" clearable :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
<el-input v-model="formData[item.fieldDbName]" :placeholder="'请输入'+item.fieldName" clearable
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
:maxlength="item.maxLength" show-word-limit></el-input>
</template>
<!-- number 输入框 -->
<template v-else-if="item.type == 'number'">
<el-input-number v-model="formData[item.fieldDbName]" :label="'请输入'+item.fieldName" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" :precision="item.decimalPlaces" :max="item.maxValue" :min="item.minValue"></el-input-number>
<el-input-number v-model="formData[item.fieldDbName]" :label="'请输入'+item.fieldName"
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)" :precision="item.decimalPlaces" :max="item.maxValue"
:min="item.minValue"></el-input-number>
</template>
<!-- textarea输入框 -->
<template v-else-if="item.type == 'textarea' || item.type == 'text'">
<el-input v-model="formData[item.fieldDbName]" :placeholder="'请输入'+item.fieldName" clearable :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
<el-input v-model="formData[item.fieldDbName]" :placeholder="'请输入'+item.fieldName" clearable
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
:maxlength="item.maxLength" type="textarea" show-word-limit :rows="3"></el-input>
</template>
<!-- 日期选择 -->
<template v-else-if="item.type == 'date'">
<el-date-picker style="width: 100%;" v-model="formData[item.fieldDbName]" type="date" placeholder="请选择" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
<el-date-picker style="width: 100%;" v-model="formData[item.fieldDbName]" type="date" placeholder="请选择"
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
:value-format="item.timePattern"></el-date-picker>
</template>
<!-- 日期带时分秒选择 -->
<template v-else-if="item.type == 'datetime'">
<el-date-picker v-model="formData[item.fieldDbName]" type="datetime" placeholder="选择日期时间" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
<el-date-picker v-model="formData[item.fieldDbName]" type="datetime" placeholder="选择日期时间"
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
:value-format="item.timePattern"></el-date-picker>
</template>
<!-- 时间-时分秒选择 -->
<template v-else-if="item.type == 'time'">
<el-time-picker v-model="formData[item.fieldDbName]" placeholder="请选择" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
<el-time-picker v-model="formData[item.fieldDbName]" placeholder="请选择"
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"
:value-format="item.timePattern"></el-time-picker>
</template>
<!-- 附件 -->
@@ -99,11 +111,13 @@
</template>
<!-- 富文本 -->
<template v-else-if="item.type == 'rtf'">
<ai-editor v-model="formData[item.fieldDbName]" :instance="instance" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"/>
<ai-editor v-model="formData[item.fieldDbName]" :instance="instance"
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"/>
</template>
<!-- 地区选择 -->
<template v-else-if="item.type == 'area'">
<ai-area-get :instance="instance" v-model="formData[item.fieldDbName]" :name.sync="formData[item.fieldDbName +'_name']" :disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"/>
<ai-area-get :instance="instance" v-model="formData[item.fieldDbName]" :name.sync="formData[item.fieldDbName +'_name']"
:disabled="item.disable == 1 || !!(formData.resident_id && item.isInit)"/>
</template>
<!-- 人员选择 -->
<div class="especial" v-else-if="item.type == 'user'">
@@ -118,23 +132,23 @@
</ai-card>
</el-form>
<ai-dialog
title="选择网格"
:visible.sync="showGrid"
:destroyOnClose="true"
@close="showGrid = false"
@onConfirm="getCheckedTree"
width="720px">
title="选择网格"
:visible.sync="showGrid"
:destroyOnClose="true"
@close="showGrid = false"
@onConfirm="getCheckedTree"
width="720px">
<div class="grid">
<el-tree
:data="treeObj.treeList"
:props="treeObj.defaultProps"
node-key="id"
ref="tree"
:check-strictly="true"
show-checkbox
:default-checked-keys="treeObj.checkedKeys"
default-expand-all
@check="onCheckChange">
:data="treeObj.treeList"
:props="treeObj.defaultProps"
node-key="id"
ref="tree"
:check-strictly="true"
show-checkbox
:default-checked-keys="treeObj.checkedKeys"
default-expand-all
@check="onCheckChange">
</el-tree>
</div>
</ai-dialog>
@@ -205,7 +219,7 @@ export default {
this.getFormData()
if (this.params.id) {
this.getDetail()
}
}
},
methods: {
getGridList() {
@@ -219,10 +233,10 @@ export default {
})
},
onChange (e) {
onChange(e) {
this.formData.resident_id = e.id
Object.keys(this.formData).forEach(item => {
for (var p in e){
for (var p in e) {
if (item === p) {
this.$set(this.formData, item, e[item])
}
@@ -249,7 +263,7 @@ export default {
this.showGrid = false
},
onCheckChange (e) {
onCheckChange(e) {
this.$nextTick(() => {
this.$refs.tree.getCheckedKeys().forEach(v => {
this.$refs.tree.setChecked(v, false)
@@ -258,16 +272,11 @@ export default {
})
},
format (list) {
format(list) {
return list.map(item => {
if (item.girdLevel !== '2') {
item.disabled = true
}
if (item.girdList && item.girdList.length) {
item.girdList = this.format(item.girdList)
}
return item
})
},
@@ -305,8 +314,7 @@ export default {
fieldValue: []
}
if (!this.params.id && item.defaultValue) {
var val = item.defaultValue?.split('`')
colItem.fieldValue = val
colItem.fieldValue = item.defaultValue?.split('`')
}
} else if (item.type === 'upload') {
@@ -333,7 +341,7 @@ export default {
if (!this.params.id) {
colItem.fieldValue = Number(item.defaultValue) || 0
}
}else {
} else {
if (item.type == 'date' && !item.timePattern) {
item.timePattern = 'yyyy-MM-dd'
}
@@ -378,9 +386,8 @@ export default {
if (res?.data) {
this.configs.tableInfos.map((item) => {
this.formData[item.fieldDbName] = res.data[item.fieldDbName] || ''
if(item.type == 'checkbox') {
var checkList = this.formData[item.fieldDbName]?.split(',')
this.formData[item.fieldDbName] = checkList
if (item.type == 'checkbox') {
this.formData[item.fieldDbName] = this.formData[item.fieldDbName]?.split(',')?.filter(e => !!e)
}
if (item.type === 'gird' && this.formData[item.fieldDbName]) {
@@ -414,20 +421,20 @@ export default {
this.formDataList.map((item) => {
if (item.length) {
item.map((items) => {
if (items.type == 'checkbox' && this.formData[items.fieldDbName].length) { //多选
this.formData[items.fieldDbName] = this.formData[items.fieldDbName]?.toString()
if (items.type == 'checkbox') { //多选
this.formData[items.fieldDbName] = this.formData[items.fieldDbName]?.filter(e => !!e)?.toString()
}
if (items.type == 'upload') {
this.formData[items.fieldDbName] = this.formData[items.fieldDbName].map(v => v.url).join(',')
}
if(items.type == 'gird' && this.formData[items.fieldDbName]) {
if (items.type == 'gird' && this.formData[items.fieldDbName]) {
this.formData[items.fieldDbName] = this.formData[items.fieldDbName] + '_' + this.girdName
}
if(items.type == 'area' && this.formData[items.fieldDbName]) {
if (items.type == 'area' && this.formData[items.fieldDbName]) {
var area = []
area.push(this.formData[items.fieldDbName])
area.push(this.formData[items.fieldDbName+'_name'])
area.push(this.formData[items.fieldDbName + '_name'])
this.formData[items.fieldDbName] = area.join('_')
}
})
@@ -462,9 +469,10 @@ export default {
</script>
<style scoped lang="scss">
::v-deep .ai-card{
::v-deep .ai-card {
width: 100%;
}
.form-div {
display: inline-block;
vertical-align: top;
@@ -474,11 +482,10 @@ export default {
::v-deep .AiPersonSelect {
.el-button {
border-color: transparent;
background-color: transparent;
color: inherit;
border-top: 0;
border-bottom: 0;
background: transparent;
background-color: transparent;
color: inherit;
border-top: 0;
border-bottom: 0;
}
}
}

View File

@@ -139,7 +139,9 @@ export default {
colItem = {label: item.fieldName, type: item.type, slot: item.fieldDbName, fieldDbName: item.fieldDbName}
} else if (item.type == 'area') {
colItem = {prop: item.fieldDbName + '_name', label: item.fieldName, align: "center"}
} else {
} else if (item.type == 'gird') {
colItem = {prop: item.fieldDbName + '_name', label: item.fieldName, align: "center"}
}else {
colItem = {prop: item.fieldDbName, label: item.fieldName, align: "center"}
}
colList.push(colItem)

View File

@@ -303,6 +303,7 @@ export default {
.is-current > .el-tree-node__content {
background: #2266ff;
min-width: 100%;
&:hover {
background: #2266ff;
@@ -315,5 +316,9 @@ export default {
}
}
}
::v-deep .is-current>.el-tree-node__content{
width: 100%!important;
padding-right: 16px!important;
}
}
</style>

View File

@@ -35,7 +35,7 @@
<h2>房屋信息</h2>
<div class="community-info__item">
<label>所属社区</label>
<span>{{ info.areaName}}</span>
<span>{{ info.areaName }}</span>
</div>
<div class="community-info__item">
<label>所属小区</label>
@@ -43,7 +43,7 @@
</div>
<div class="community-info__item">
<label>房屋类型</label>
<span>{{ dict.getLabel("communityBuildingType",info.buildingType) }}</span>
<span>{{ dict.getLabel("communityBuildingType", info.buildingType) }}</span>
</div>
<div class="community-info__item">
<label>楼长姓名</label>
@@ -51,7 +51,7 @@
</div>
<div class="community-info__item">
<label>楼长电话</label>
<span>{{ info.managerPhone}}</span>
<span>{{ info.managerPhone }}</span>
</div>
</div>
@@ -59,7 +59,7 @@
<h2>人员信息</h2>
<div class="community-info__item">
<label>姓名</label>
<span style="color:#2266FF;">{{ resident.name}}</span>
<span style="color:#2266FF;">{{ resident.name }}</span>
</div>
<div class="community-info__item">
<label>所属单元</label>
@@ -67,7 +67,7 @@
</div>
<div class="community-info__item">
<label>房号</label>
<span>{{house.houseCode}}</span>
<span>{{ house.houseCode }}</span>
</div>
<div class="community-info__item">
<label>联系方式</label>
@@ -86,7 +86,8 @@
<!-- </div>-->
<div class="community-btn">
<el-button icon="iconfont iconloudongmoxing" size="small"
@click="$router.push({query: {communityId: info.communityId, buildingId: info.id,unitNum:house ? house.unitNumber : 1,buildingNumber:info.buildingNumber}})">楼栋模型
@click="$router.push({query: {communityId: info.communityId, buildingId: info.id,unitNum:house ? house.unitNumber : 1,buildingNumber:info.buildingNumber}})">
楼栋模型
</el-button>
</div>
</div>
@@ -153,19 +154,19 @@ export default {
list: [],
areaList: [],
info: {},
resident:null,
resident: null,
satellite: null,
zoom: 11,
chooseBuildId: '',
buildList: [],
searchList: [],
house:null,
center: []
house: null,
center: [],
mapLib: null
}
},
computed: {
...mapState(['user']),
hasCommunityId() {
return !!this.$route.query?.communityId
}
@@ -186,7 +187,7 @@ export default {
},
created() {
this.dict.load('householdRelation','communityBuildingType')
this.dict.load('householdRelation', 'communityBuildingType')
},
mounted() {
@@ -198,9 +199,9 @@ export default {
},
methods: {
getCorpLocation(){
this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res=>{
if(res.code==0){
getCorpLocation() {
this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res => {
if (res.code == 0) {
this.initMap(res.data);
}
})
@@ -239,9 +240,9 @@ export default {
},
getBuildInfo(id) {
this.instance.post(`/app/appcommunityhouseinfo/queryDetailByIdWithBuilding`,null,{
params:{
buildId:id
this.instance.post(`/app/appcommunityhouseinfo/queryDetailByIdWithBuilding`, null, {
params: {
buildId: id
}
}).then(res => {
if (res.code === 0) {
@@ -255,11 +256,11 @@ export default {
},
chooseCommunity(item) {
this.instance.post(`/app/appcommunityhouseinfo/queryDetailByIdWithBuilding`,null,{
params:{
buildId:item.buildingId,
houseId:item.id,
residentId:item.residentId
this.instance.post(`/app/appcommunityhouseinfo/queryDetailByIdWithBuilding`, null, {
params: {
buildId: item.buildingId,
houseId: item.id,
residentId: item.residentId
}
}).then(res => {
if (res.code === 0) {
@@ -293,7 +294,7 @@ export default {
<div class="polymeric-container">
<p>${context.count}</p>
</div>
</div>`
</div>`, {mapLib: AMap} = this
let offset = new AMap.Pixel(-9, -9)
context.marker.setContent(el)
@@ -308,12 +309,12 @@ export default {
renderMarker(context) {
const buildId = context.data[0].id
let el = `<div class="mark" id="buildId-${buildId}" style="${buildId === this.chooseBuildId?'background-color:#2266FF':''}">
let el = `<div class="mark" id="buildId-${buildId}" style="${buildId === this.chooseBuildId ? 'background-color:#2266FF' : ''}">
<div class="mark-contaienr">
<span>${context.data[0].communityName}</span>&nbsp;&nbsp;
<span>${context.data[0].buildingNumber}栋</span>
</div>
<div class="arrow" style="${buildId === this.chooseBuildId?'border-top-color: #2266FF':''}"></div>
<div class="arrow" style="${buildId === this.chooseBuildId ? 'border-top-color: #2266FF' : ''}"></div>
</div>`
context.marker.setContent(el);
@@ -336,6 +337,7 @@ export default {
},
addMakert(points) {
let {mapLib: AMap} = this
new AMap.MarkerClusterer(this.map, points, {
gridSize: 60,
maxZoom: 15,
@@ -352,29 +354,26 @@ export default {
size: 1000000
}
}).then(res => {
if (res.code === 0) {
if (res?.data) {
this.buildList = res.data.records
const points = res.data.records.map(item => {
return {
lnglat: [item.lng, item.lat],
id: item.id,
corpId: item.corpId,
areaName:item.areaName,
buildingNumber:item.buildingNumber,
communityName:item.communityName
areaName: item.areaName,
buildingNumber: item.buildingNumber,
communityName: item.communityName
}
})
this.addMakert(points)
}
})
},
hidePopup() {
this.isShowArea = false
this.isShowSearch = false
},
switchLayer(flag) {
if (flag) {
this.map.addLayer(this.satellite)
@@ -384,9 +383,8 @@ export default {
this.isImageMap = flag
},
initMap({lng,lat}) {
this.center = [lng,lat];
initMap({lng, lat}) {
this.center = [lng, lat];
AMapLoader.load({
key: 'b553334ba34f7ac3cd09df9bc8b539dc',
version: '2.0',
@@ -396,6 +394,7 @@ export default {
plugins: []
}
}).then((AMap) => {
this.mapLib = AMap
this.map = new AMap.Map('map', {
resizeEnable: true,
zooms: [6, 20],
@@ -422,7 +421,7 @@ export default {
width: 100%;
}
::v-deep .ai-list__content--right-wrapper{
::v-deep .ai-list__content--right-wrapper {
height: 100%;
margin: 0px !important;
background-color: transparent !important;
@@ -804,7 +803,7 @@ export default {
white-space: nowrap;
}
p:first-child{
p:first-child {
font-size: 14px;
}
@@ -816,7 +815,7 @@ export default {
}
}
::v-deep .mark{
::v-deep .mark {
user-select: none;
cursor: pointer;
height: 32px;
@@ -829,7 +828,7 @@ export default {
box-sizing: border-box;
padding: 0 12px;
.mark-contaienr{
.mark-contaienr {
color: white;
font-size: 14px;
position: relative;
@@ -841,7 +840,7 @@ export default {
justify-content: center;
}
.arrow{
.arrow {
position: absolute;
left: 50%;
transform: translateX(-50%);

View File

@@ -1,74 +1,75 @@
<template>
<section class="buildingStatistics">
<ai-title v-if="!isFormDv" title="楼栋统计" isShowBack isShowBottomBorder @onBackClick="$router.push({query:{}}),$parent.info={},$parent.isShowInfo=false,$parent.house=null,$parent.chooseBuildId=''"/>
<ai-title v-if="!isFormDv" title="楼栋统计" isShowBack isShowBottomBorder
@onBackClick="$router.push({query:{}}),$parent.info={},$parent.isShowInfo=false,$parent.house=null,$parent.chooseBuildId=''"/>
<div class="buildingPane">
<div class="bgItem tree"/>
<div class="building">
<template v-if="floorRooms.length>0">
<div class="buildingSignboard">{{ `${currentBuilding.buildingNumber}${unitNumber}单元` }}
</div>
<el-scrollbar class="floors">
<div class="floor" v-for="(fl,j) in floorRooms" :key="j">
<div class="room" v-for="(op,i) in fl" :key="op.id" @click="handleSelectRoom(op,$event)" @touchstart="handleSelectRoom(op,$event)" :class="[{none:op.livingNumber==0,selected:selected.houseCode==op.houseCode},handleTipsHighlight(op.tips)]">
{{ op.houseCode }}
<div v-if="op.livingNumber==0">无人</div>
<div v-show="op.id==selected.id" class="detail" @click.stop :style="{left:position.x,top:position.y}">
<el-row class="popupHeader" type="flex" justify="space-between" align="middle">
<span>{{selected.houseCode}}详情</span>
<ai-icon icon="iconClean" @click.native.stop="selected={}"/>
</el-row>
<div class="family-member">
<h2>房主信息</h2>
<div v-for="(item,index) in selected.owner" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{item.name}}</label>
</div>
<span style="color: #2266FF">{{root.dict.getLabel("houseLivingType",item.livingType)}}</span>
</div>
<div class="family-member__item">
<div class="member-left">
<label>联系方式</label>
</div>
<span style="color: #2266FF;">{{item.phone}}</span>
<div class="building">
<template v-if="floorRooms.length>0">
<div class="buildingSignboard" v-text="`${currentBuilding.buildingNumber}栋 ${unitNumber}单元`"/>
<el-scrollbar class="floors">
<div class="floor" v-for="(fl,j) in floorRooms" :key="j">
<div class="room" v-for="op in fl" :key="op.id" @click="handleSelectRoom(op,$event)" @touchstart="handleSelectRoom(op,$event)"
:class="[{none:op.livingNumber==0,selected:selected.houseCode==op.houseCode},handleTipsHighlight(op.tips)]">
{{ op.houseCode }}
<div v-if="op.livingNumber==0">无人</div>
<div v-show="op.id==selected.id" class="detail" @click.stop :style="{left:position.x,top:position.y}">
<el-row class="popupHeader" type="flex" justify="space-between" align="middle">
<span>{{ selected.houseCode }}详情</span>
<ai-icon icon="iconClean" @click.native.stop="selected={}"/>
</el-row>
<div class="family-member">
<h2>房主信息</h2>
<div v-for="(item,index) in selected.owner" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{ item.name }}</label>
</div>
<span style="color: #2266FF">{{ root.dict.getLabel("houseLivingType", item.livingType) }}</span>
</div>
<h2>承租人信息</h2>
<div v-for="(item,index) in selected.renter" :key="item.id">
<div class="family-member__item" >
<div class="member-left">
<label>{{item.name}}</label>
</div>
<span style="color: #2266FF">{{root.dict.getLabel("houseLivingType",item.livingType)}}</span>
</div>
<div class="family-member__item">
<div class="member-left">
<label>联系方式</label>
</div>
<span>{{item.phone}}</span>
<div class="family-member__item">
<div class="member-left">
<label>联系方式</label>
</div>
<span style="color: #2266FF;">{{ item.phone }}</span>
</div>
</div>
<h2>实际居住人员</h2>
<div v-for="(item,index) in selected.live" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{item.name}}</label>
</div>
<span>{{root.dict.getLabel("householdRelation",item.relation)}}</span>
<h2>承租人信息</h2>
<div v-for="(item,index) in selected.renter" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{ item.name }}</label>
</div>
<span style="color: #2266FF">{{ root.dict.getLabel("houseLivingType", item.livingType) }}</span>
</div>
<div class="family-member__item">
<div class="member-left">
<label>联系方式</label>
</div>
<span>{{ item.phone }}</span>
</div>
</div>
<h2>实际居住人员</h2>
<div v-for="(item,index) in selected.live" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{ item.name }}</label>
</div>
<span>{{ root.dict.getLabel("householdRelation", item.relation) }}</span>
</div>
</div>
</div>
</div>
</div>
</el-scrollbar>
</template>
<ai-empty v-else>请在<b>小区总览</b>中选取楼栋单元</ai-empty>
<div class="bottom"/>
</div>
<building-tool-bar></building-tool-bar>
</div>
</el-scrollbar>
</template>
<ai-empty v-else>请在<b>小区总览</b>中选取楼栋单元</ai-empty>
<div class="bottom"/>
</div>
<building-tool-bar/>
</div>
</section>
</template>
@@ -96,11 +97,11 @@ export default {
rooms: [],
selected: {},
currentBuilding: {},
unitNumber:1,
unitNumber: 1,
tips: [],
position:{
x:"",
y:""
position: {
x: "",
y: ""
},
}
},
@@ -115,23 +116,23 @@ export default {
}
},
created() {
this.dict.load('householdRelation', 'residentTipType',"houseLivingType")
this.dict.load('householdRelation', 'residentTipType', "houseLivingType")
if (this.isFormDv && this.query.buildingId) {
this.getRoomsByBuilding(this.query.buildingId, this.query.unitNum)
this.currentBuilding = { buildingNumber: this.query.buildingNumber}
this.currentBuilding = {buildingNumber: this.query.buildingNumber}
this.unitNumber = this.query.unitNum
return false
}
this.getRoomsByBuilding(this.$route.query?.buildingId,this.$route.query?.unitNum)
this.getRoomsByBuilding(this.$route.query?.buildingId, this.$route.query?.unitNum)
this.currentBuilding = {buildingNumber: this.$route.query?.buildingNumber};
this.unitNumber = this.$route.query?.unitNum;
},
methods: {
handleSelectRoom(room, e) {
console.log(e)
if (room.livingNumber>0) {
this.$nextTick(()=>{
if (room.livingNumber > 0) {
this.$nextTick(() => {
this.position.x = e.pageX + 40 + "px"
this.position.y = e.pageY + "px"
this.selected = room;
@@ -140,15 +141,17 @@ export default {
// this.getRoomDetail(room.id)
}
},
selectedBuilding(building,unitNumber) {
selectedBuilding(building, unitNumber) {
this.selected = {}
this.tips = []
this.$router.push({query: {...this.$route.query, buildingId: building.id,unitNum:unitNumber}}).catch(e=>{e})
this.$router.push({query: {...this.$route.query, buildingId: building.id, unitNum: unitNumber}}).catch(e => {
e
})
this.currentBuilding = building
this.unitNumber = unitNumber
this.getRoomsByBuilding(building.id,unitNumber)
this.getRoomsByBuilding(building.id, unitNumber)
},
getRoomsByBuilding(buildingId,unitNumber) {
getRoomsByBuilding(buildingId, unitNumber) {
this.root.instance.post("/app/appcommunityhouseinfo/list", null, {
params: {
unitNumber,
@@ -170,11 +173,11 @@ export default {
this.selected = {
...this.selected, ...res.data,
residents: residents.map(e => {
let {tips} = e
//显示为户主
let relationLabel = e.householdName == 1 ? "户主" : this.root.dict.getLabel("householdRelation", e.householdRelation)
return {...e, tips: tips ? tips.split("|") : [], relationLabel}
}
let {tips} = e
//显示为户主
let relationLabel = e.householdName == 1 ? "户主" : this.root.dict.getLabel("householdRelation", e.householdRelation)
return {...e, tips: tips ? tips.split("|") : [], relationLabel}
}
)
}
}
@@ -197,7 +200,7 @@ export default {
display: flex;
flex-direction: column;
::v-deep .ailist-title{
::v-deep .ailist-title {
margin: 0 20px;
}
@@ -337,29 +340,37 @@ export default {
::v-deep .floors {
max-height: 520px;
max-width: 60vw;
margin: 0 20px;
padding: 0 50px;
position: relative;
.el-scrollbar__wrap {
overflow-x: hidden;
margin-bottom: 0 !important;
&:before {
display: block;
content: " ";
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-image: url("https://cdn.cunwuyun.cn/buildSta/floor.png");
background-size: 100% 105px;
}
}
.floor {
margin: 0 20px;
position: relative;
height: 105px;
flex-shrink: 0;
max-width: calc(100% - 40px);
display: flex;
flex-shrink: 0;
align-items: center;
background-image: url("https://cdn.cunwuyun.cn/buildSta/floor.png");
background-size: 100% 105px;
padding: 0 30px;
box-sizing: border-box;
gap: 20px;
.room {
width: 60px;
height: 72px;
flex-shrink: 0;
background-image: url("https://cdn.cunwuyun.cn/buildSta/room.png");
text-align: center;
padding-top: 20px;

View File

@@ -5,8 +5,8 @@
<div class="building" v-for="(value,name) in buildingUnits" :key="name">
<div class="unit" v-for="(op,j) in value" :key="j" @click="sta.selectedBuilding(op,j+1)"
:class="{selected:sta.unitNumber==j+1 && sta.currentBuilding.buildingNumber==name}">
<b>{{ name}}</b>
<div>{{ j+1 }}单元</div>
<b>{{ name }}</b>
<div>{{ j + 1 }}单元</div>
</div>
</div>
</div>
@@ -22,7 +22,7 @@ export default {
buildingUnits() {
let obj = {}
this.units.map(e => {
for(let i=0;i<e.unitNumber;i++){
for (let i = 0; i < e.unitNumber; i++) {
obj[e.buildingNumber]?.push(e) || (obj[e.buildingNumber] = [e])
}
})
@@ -57,6 +57,8 @@ export default {
<style lang="scss" scoped>
.communityOverview {
max-width: 400px;
max-height: 600px;
overflow-y: auto!important;
.units {
display: flex;
@@ -68,7 +70,7 @@ export default {
display: flex;
align-items: center;
height: auto;
flex-wrap: wrap;
flex-wrap: wrap;
.unit {
margin-right: 10px;

View File

@@ -43,7 +43,12 @@
<el-tree :data="treeObj.treeList" :props="treeObj.defaultProps" node-key="id" ref="tree"
:check-strictly="true" show-checkbox
:default-checked-keys="treeObj.checkedKeys" default-expand-all
@check="onCheckChange">
@check="onCheckChange">
<template slot-scope="{node,data}">
<el-tooltip :content="node.label">
<div class="el-tree-node__label" v-text="node.label"/>
</el-tooltip>
</template>
</el-tree>
</div>
<div class="dialog-footer" slot="footer">
@@ -131,7 +136,7 @@ export default {
});
},
onCheckChange (e) {
onCheckChange(e) {
this.$nextTick(() => {
this.$refs.tree.getCheckedKeys().forEach(v => {
this.$refs.tree.setChecked(v, false)
@@ -140,12 +145,8 @@ export default {
})
},
format (list) {
format(list) {
return list.map(item => {
if (item.girdLevel !== '2') {
item.disabled = true
}
if (item.girdList && item.girdList.length) {
item.girdList = this.format(item.girdList)
}

View File

@@ -1,16 +1,6 @@
<template>
<div class="AppGridBlock">
<keep-alive include="List">
<component
ref="component"
:is="component"
@change="onChange"
:params="params"
:instance="instance"
:dict="dict"
:isEdit="isEdit"
></component>
</keep-alive>
<component :is="currentPage" :instance="instance" :dict="dict"/>
</div>
</template>
@@ -26,44 +16,17 @@ export default {
instance: Function,
dict: Object,
},
computed: {
currentPage() {
return this.$route.hash == "#add" ? Add : List
}
},
data() {
return {
component: "List",
params: {},
include: [],
isEdit: false
};
},
components: {
Add,
List,
},
mounted() {},
methods: {
onChange(data) {
if (data.type === "Add") {
this.component = "Add";
this.params = data.params;
this.isEdit = data.isEdit
}
if (data.type === "list") {
this.component = "List";
this.params = data.params;
this.$nextTick(() => {
if (data.isRefresh) {
this.$refs.component.getList()
this.$refs.component.getTreeList()
}
});
}
},
},
components: {Add, List},
};
</script>

View File

@@ -3,151 +3,56 @@
<ai-detail>
<template #title>
<ai-title
:title="title"
:title="pageTitle"
:isShowBack="true"
:isShowBottomBorder="true"
@onBackClick="cancel(false)"
></ai-title>
/>
</template>
<template #content>
<ai-card title="层级信息">
<template slot="content">
<ai-wrapper label-width="120px" :columnsNumber="2" style="margin-top: 16px">
<ai-info-item label="上级层级单位:"><span>{{ forms.parentGirdName }}</span></ai-info-item>
</ai-wrapper>
</template>
</ai-card>
<el-form
ref="rules"
:model="forms"
:rules="formRules"
size="small"
label-suffix=""
label-width="120px"
>
<el-form ref="rules" :model="forms" :rules="formRules" size="small" label-suffix="" label-width="120px">
<ai-card title="基础信息">
<template slot="content">
<div class="above">
<div class="left">
<el-form-item label="网格名称" prop="girdName">
<el-input
v-model="forms.girdName"
placeholder="请输入…"
:maxlength="50"
show-word-limit
></el-input>
</el-form-item>
<el-form-item label="网格类型" prop="girdType">
<el-select
v-model="forms.girdType"
placeholder="请选择"
clearable
style="width: 100%;"
>
<el-option
v-for="(item, i) in dict.getDict('girdType')"
:key="i"
:label="item.dictName"
:value="item.dictValue"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否最后一级" prop="isLastLevel">
<el-select
v-model="forms.isLastLevel"
placeholder="请选择"
clearable
style="width: 100%;"
>
<el-option
v-for="(item, i) in dict.getDict('isLastLevel')"
:key="i"
:label="item.dictName"
:value="item.dictValue"
></el-option>
</el-select>
</el-form-item>
</div>
<div class="right">
<el-form-item label="网格编码" prop="girdCode">
<el-input
v-model="forms.girdCode"
placeholder="请输入…"
maxlength="30"
show-word-limit
></el-input>
</el-form-item>
<el-form-item label="网格层级" prop="girdLevel">
<el-select
v-model="forms.girdLevel"
placeholder="请选择"
:disabled="isEdit"
clearable
style="width: 100%;"
>
<el-option
v-for="(item, i) in dict.getDict('girdLevel')"
:key="i"
:label="item.dictName"
:value="item.dictValue"
></el-option>
</el-select>
</el-form-item>
</div>
</div>
<el-form-item label="网格名称" prop="girdName">
<el-input v-model="forms.girdName" placeholder="请输入…" :maxlength="50" show-word-limit clearable/>
</el-form-item>
<el-form-item label="网格长" prop="girdMemberManageList">
<ai-user-picker :instance="instance" v-model="forms.girdMemberManageList" :props="{label:'name', id: 'id'}"/>
</el-form-item>
<el-form-item label="网格员" prop="girdMemberList">
<ai-user-picker :instance="instance" v-model="forms.girdMemberList" :props="{label:'name', id: 'id'}"/>
</el-form-item>
</template>
</ai-card>
<ai-card title="其他信息">
<template slot="content">
<div class="above">
<div class="left">
<!-- <el-form-item label="事件上报主体" prop="eventReportUnitId">
<el-cascader
style="width: 100%"
:options="unitOps"
ref="cascader"
v-model="forms.eventReportUnitId"
:props="unitProps"
:show-all-levels="false"
/>
</el-form-item> -->
<el-row type="flex">
<div class="fill">
<el-form-item label="初始日期" prop="startDate">
<el-date-picker
v-model="forms.startDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期"
style="width: 100%;"
>
</el-date-picker>
style="width: 100%;"/>
</el-form-item>
<el-form-item label="终止日期" prop="endDate">
<el-date-picker
v-model="forms.endDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期"
style="width: 100%;"
>
</el-date-picker>
<el-date-picker v-model="forms.endDate" type="date" value-format="yyyy-MM-dd" placeholder="选择日期" style="width: 100%;"/>
</el-form-item>
</div>
<div class="right">
<div class="fill">
<el-form-item label="面积" prop="area">
<el-input
v-model="forms.area"
placeholder="面积㎡"
></el-input>
<el-input v-model="forms.area" placeholder="面积㎡" clearable/>
</el-form-item>
</div>
</div>
</el-row>
<el-form-item label="网格地址" prop="address">
<el-input v-model="forms.address" placeholder="限200字" maxlength="200"></el-input>
</el-form-item>
<el-form-item label="网格范围" prop="enclosure" v-if="forms.girdLevel === '2' || isAddLastLevel">
<el-button size="small" @click="showMap = true">地图标绘</el-button>
<el-form-item label="网格范围" prop="enclosure">
<map-plotting v-model="forms.points">
<el-button size="small">地图标绘</el-button>
</map-plotting>
</el-form-item>
</template>
</ai-card>
@@ -162,110 +67,30 @@
</el-button>
</template>
</ai-detail>
<ai-dialog
title="网格范围"
:visible.sync="showMap"
:customFooter="true"
:destroyOnClose="true"
@opened="beforeSelectMap"
border
width="850px"
>
<div class="map">
<div class="tipinput">
<el-input
v-model="searchAddress"
@change="addressChange"
clearable
placeholder="请输入关键字"
id="tipinput"
size="medium"
style="width: 200px"
></el-input>
</div>
<div id="panel"></div>
<div class="container" id="container"></div>
<el-button-group
style="margin-top: 8px"
v-if="forms.plottingStatus == 1"
>
<el-button type="primary" size="mini" @click="polyEditor.open()"
>开始编辑
</el-button
>
<el-button size="mini" @click="polyEditor.close()"
>结束编辑
</el-button
>
</el-button-group>
<el-button-group
style="margin-top: 8px"
v-if="forms.plottingStatus == 0"
>
<el-button size="mini" @click="draw('polygon')"
>开始绘制多边形
</el-button
>
<!-- <el-button size="mini" @click="close()">关闭绘制</el-button> -->
<el-button size="mini" @click="clear()">清除绘制</el-button>
</el-button-group>
</div>
<div class="dialog-footer" slot="footer">
<el-button size="medium" @click="showMap = false">取消</el-button>
<el-button type="primary" size="medium" @click="surePotting()"
>确认
</el-button
>
</div>
</ai-dialog>
</div>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader";
import {mapState} from "vuex";
import MapPlotting from "./mapPlotting";
import AiUserPicker from "../../components/AiUserPicker";
export default {
name: "addBlock",
components: {AiUserPicker, MapPlotting},
props: {
instance: Function,
dict: Object,
params: Object,
isEdit: Boolean
},
data() {
return {
forms: {
address: "",
area: "",
points: [],
endDate: "",
eventReportUnit: "",
eventReportUnitId: "",
girdCode: "",
girdLevel: "",
girdList: [],
girdName: "",
girdType: "",
isLastLevel: "",
parentGirdId: "",
parentGirdName: "",
startDate: "",
plottingStatus: "0",
girdMemberManageList: [],
girdMemberList: []
},
showMap: false,
map: "",
mouseTool: "",
searchAddress: "",
placeSearch: "",
overlays: [],
options: [],
path: [],
location: {},
polyEditor: "",
title: "添加网格区块",
parentGirdInfo: {},
isAddLastLevel: false
};
},
computed: {
@@ -275,9 +100,6 @@ export default {
girdName: [
{required: true, message: "请输入网格名称", trigger: "change"},
],
girdLevel: [
{required: true, message: "请选择网格层级", trigger: "change"},
],
girdCode: [
{required: true, message: "请输入网格编号"},
{pattern: /^\d+$/g, message: "请输入数字"},
@@ -297,28 +119,26 @@ export default {
ops.map((e) => this.addChild(e, initData));
return ops;
},
pageTitle() {
return this.isEdit ? "编辑网格区块" : "添加网格区块"
},
isEdit() {
return !!this.$route.query.id;
}
},
created() {
this.getCorpLocation()
if (this.isEdit) {
this.title = "编辑网格区块";
this.searchDetail();
} else {
this.forms.parentGirdId = this.params.id;
this.forms.parentGirdName = this.params.girdName;
this.isAddLastLevel = this.params.girdLevel === '1'
// this.forms.girdLevel = Number(this.info.girdLevel) + 1 +'';
// this.forms.isLastLevel = ['0','1'].includes(this.forms.girdLevel)?'0':'1';
this.title = "添加网格区块";
this.forms = {
...this.forms,
...this.$route.query
}
}
// this.getAllUnit(this.user.info.areaId);
},
methods: {
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh,
})
cancel() {
this.$router.push({})
},
// 获取所有单位
getAllUnit(data) {
@@ -335,159 +155,15 @@ export default {
}
});
},
beforeSelectMap() {
AMapLoader.load({
key: "b553334ba34f7ac3cd09df9bc8b539dc", // 申请好的Web端开发者Key首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["AMap.MouseTool", "AMap.PlaceSearch", "AMap.PolygonEditor"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
AMapUI: {
// 是否加载 AMapUI缺省不加载
version: "1.1", // AMapUI 缺省 1.1
plugins: [], // 需要加载的 AMapUI ui插件
},
})
.then((AMap) => {
this.map = new AMap.Map("container", {
resizeEnable: true,
});
if (this.forms.plottingStatus == 1) {
let path = [];
this.forms.points.map((e, index) => {
path[index] = [e.lng, e.lat];
});
let polygon = new AMap.Polygon({
path: path,
strokeColor: "#FF33FF",
strokeWeight: 6,
strokeOpacity: 0.2,
fillOpacity: 0.4,
fillColor: "#1791fc",
zIndex: 50,
bubble: true,
});
this.map.add([polygon]);
this.map.setFitView();
this.polyEditor = new AMap.PolygonEditor(this.map, polygon);
} else {
this.mouseTool = new AMap.MouseTool(this.map);
// this.map.add(new AMap.Marker({
// position:this.map.getCenter()
// }));
this.placeSearch = new AMap.PlaceSearch({
pageSize: 3, // 单页显示结果条数
pageIndex: 1, // 页码
city: "", // 兴趣点城市
citylimit: false, //是否强制限制在设置的城市内搜索
map: this.map, // 展现结果的地图实例
panel: "panel", // 结果列表将在此容器中进行展示。
autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
});
this.map.setZoomAndCenter(14, [this.location.lng, this.location.lat], false, 600);
this.eventOn();
}
})
},
getCorpLocation() {
this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res => {
if (res.code == 0) {
this.location = res.data
}
})
},
//地图事件绑定
eventOn() {
this.path = [];
this.overlays = [];
this.map.on("mousemove", null, this);
this.mouseTool.on("draw", ({obj}) => {
obj.getPath().map((e) => {
this.path.push({lat: e.getLat(), lng: e.getLng()});
});
this.overlays.push(obj);
})
},
//map搜索
addressChange(val) {
this.placeSearch.search(val);
},
close() {
this.mouseTool.close(true);
},
clear() {
this.map.remove(this.overlays);
this.overlays = [];
this.path = [];
},
draw(type) {
switch (type) {
case "marker": {
this.mouseTool.marker({
//同Marker的Option设置
});
break;
}
case "polyline": {
this.mouseTool.polyline({
strokeColor: "#80d8ff",
//同Polyline的Option设置
});
break;
}
case "polygon": {
this.mouseTool.polygon({
fillColor: "#00b0ff",
strokeColor: "#80d8ff",
borderWeight: 2,
strokeWeight: 4,
//同Polygon的Option设置
});
break;
}
case "rectangle": {
this.mouseTool.rectangle({
fillColor: "#00b0ff",
strokeColor: "#80d8ff",
//同Polygon的Option设置
});
break;
}
case "circle": {
this.mouseTool.circle({
fillColor: "#00b0ff",
strokeColor: "#80d8ff",
//同Circle的Option设置
});
break;
}
}
},
surePotting() {
this.forms.points = [];
// this.forms.eventReportUnit = this.$refs.cascader.getCheckedNodes().label;
if (this.forms.plottingStatus == 1) {
this.polyEditor
.getTarget()
.getPath()
.map((e) => {
this.forms.points.push({lng: e.lng, lat: e.lat});
});
} else {
this.forms.points = [...this.path];
}
this.showMap = false;
},
save() {
this.$refs["rules"].validate((valid) => {
if (valid) {
this.instance
.post(
`/app/appgirdinfo/addOrUpdate`,
{
...this.forms,
},
null
)
.then((res) => {
let {girdMemberManageList, girdMemberList} = this.forms
this.instance.post(`/app/appgirdinfo/addOrUpdate`, {
...this.forms,
girdMemberManageList: girdMemberManageList?.map(v => ({wxUserId: v.id})) || [],
girdMemberList: girdMemberList?.map(v => ({wxUserId: v.id})) || []
}).then((res) => {
if (res.code == 0) {
this.cancel(true)
}
@@ -499,11 +175,26 @@ export default {
});
},
searchDetail() {
let {id} = this.$route.query
this.instance.post(`/app/appgirdinfo/queryDetailById`, null, {
params: {id: this.params.id},
params: {id},
}).then((res) => {
if (res?.data) {
this.forms = {...res.data};
this.forms = {
...res.data,
girdMemberManageList: res.data.girdMemberManageList ? res.data.girdMemberManageList.map(v => {
return {
...v,
id: v.wxUserId
}
}) : [],
girdMemberList: res.data.girdMemberList ? res.data.girdMemberList.map(v => {
return {
...v,
id: v.wxUserId
}
}) : []
};
this.parentGirdInfo = res.data.parentGirdInfo;
this.forms.parentGirdName = res.data.parentGirdInfo && res.data.parentGirdInfo.girdName;
}
@@ -518,63 +209,8 @@ export default {
width: 100%;
height: 100%;
::v-deep .amap-copyright {
display: none !important;
}
::v-deep .amap-logo {
display: none !important;
}
.above {
overflow: hidden;
padding: 8px 0;
.left {
width: 380px;
float: left;
}
.right {
width: 380px;
float: right;
}
}
.footer-btn {
width: 92px;
}
.map {
width: 780px;
position: relative;
overflow: hidden;
.container {
width: 760px;
height: 420px;
border-radius: 2px;
border: 1px solid #d0d4dc;
}
#panel {
position: absolute;
height: 400px;
right: 30px;
top: 20px;
width: 280px;
overflow: hidden;
z-index: 10000;
}
.tipinput {
position: absolute;
width: 200px;
height: 38px;
left: 20px;
top: 20px;
z-index: 10000;
}
}
}
</style>

View File

@@ -1,84 +1,86 @@
<template>
<div class="app-grid-block">
<section class="app-grid-block">
<ai-list>
<template slot="title">
<ai-title title="网格区块" :isShowBottomBorder="true"></ai-title>
</template>
<template slot="left">
<ai-tree-menu title="网格层级" @search="(v) => $refs.tree.filter(v)">
<ai-tree-menu title="网格层级" @search="v=> $refs.tree.filter(v)">
<el-tree
:data="treeObj.treeList"
:props="treeObj.defaultProps"
@node-click="handleNodeClick"
node-key="id"
ref="tree"
:filter-node-method="filterNode"
default-expand-all
highlight-current
/>
:data="treeObj.treeList"
:props="treeObj.defaultProps"
@node-click="handleNodeClick"
node-key="id"
ref="tree"
:filter-node-method="filterNode"
default-expand-all
highlight-current>
<template slot-scope="{node,data}">
<div v-text="node.label"/>
</template>
</el-tree>
</ai-tree-menu>
</template>
<template slot="content">
<ai-search-bar>
<template slot="left">
<el-date-picker
v-model="searchObj.createTimeStr"
type="date"
@change="(page.current = 1), getList()"
value-format="yyyy-MM-dd"
size="small"
placeholder="创建时间"
v-model="searchObj.createTimeStr"
type="date"
@change="(page.current = 1), getList()"
value-format="yyyy-MM-dd"
size="small"
placeholder="创建时间"
>
</el-date-picker>
</template>
<template slot="right">
<el-input
v-model="searchObj.girdName"
size="small"
placeholder="输入网格名称"
@keyup.enter.native="(page.current = 1), getList()"
clearable
v-throttle="() => {page.current = 1, getList()}"
@clear="(searchObj.girdName = '', page.current = 1), getList()"
suffix-icon="iconfont iconSearch"
v-model="searchObj.girdName"
size="small"
placeholder="输入网格名称"
@keyup.enter.native="(page.current = 1), getList()"
clearable
@clear="(searchObj.girdName = '', page.current = 1), getList()"
suffix-icon="iconfont iconSearch"
/>
</template>
</ai-search-bar>
<ai-search-bar bottomBorder>
<template slot="left">
<el-button
type="primary"
icon="iconfont iconAdd"
:disabled="info.girdLevel === '3'"
@click="(isEdit = false), toAdd()"
>新增
type="primary"
icon="iconfont iconAdd"
@click="(isEdit = false), toAdd()"
>新增
</el-button>
<el-button
icon="iconfont iconDelete"
@click="deleteById(ids.join(','))"
:disabled="!Boolean(ids.length)"
icon="iconfont iconDelete"
@click="deleteById(ids.join(','))"
:disabled="!Boolean(ids.length)"
>
删除
</el-button>
<ai-download
:instance="instance"
url="/app/appgirdinfo/exportGirdInfo"
:params="{ ...searchObj, ids: ids.join(',') }"
fileName="网格区块"
:instance="instance"
url="/app/appgirdinfo/exportGirdInfo"
:params="{ ...searchObj, ids: ids.join(',') }"
fileName="网格区块"
>
<el-button icon="iconfont iconExported" size="small"
>导出全部</el-button
>导出全部
</el-button
>
</ai-download>
<ai-import
ref="import"
title="导入"
name="网格区块"
url="/app/appgirdinfo/downloadGirdInfo"
importUrl="/app/appgirdinfo/importGirdInfo"
suffixName="xlsx"
:customCliker="true"
:instance="instance"
ref="import"
title="导入"
name="网格区块"
url="/app/appgirdinfo/downloadGirdInfo"
importUrl="/app/appgirdinfo/importGirdInfo"
suffixName="xlsx"
:customCliker="true"
:instance="instance"
>
<template slot="tips">
<p>
@@ -86,104 +88,60 @@
</p>
</template>
<el-button size="small" icon="iconfont iconImport"
>导入</el-button
>导入
</el-button
>
</ai-import>
</template>
</ai-search-bar>
<ai-table
class="mt10"
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
ref="aitableex"
:current.sync="page.current"
:size.sync="page.size"
@selection-change="(v) => (ids = v.map((e) => e.id))"
@getList="getList()"
>
<el-table-column
slot="selectId"
type="selection"
align="center"
width="40"
>
class="mt10"
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
ref="aitableex"
:current.sync="page.current"
:size.sync="page.size"
@selection-change="v=>ids=v.map((e) => e.id)"
@getList="getList()"
:dict="dict">
<el-table-column label="网格成员" slot="user" align="center" width="160">
<template slot-scope="{ row }">
<el-button type="text" @click="showGridMembers(row)">{{ row.girdMemberNumber || 0 }}</el-button>
</template>
</el-table-column>
<el-table-column
label="操作"
slot="options"
align="center"
fixed="right"
width="160">
label="操作"
slot="options"
align="center"
fixed="right"
width="160">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="see(row)">编辑</el-button>
<el-button type="text" @click="poltting(row)" :disabled="row.girdLevel !== '2'">标绘</el-button>
<el-button type="text" @click="deleteById(row.id)">删除</el-button>
</div>
<el-button type="text" @click="showEdit(row.id)">编辑</el-button>
<map-plotting :value="row.points" @change="v=>confirm(row,v)"/>
<el-button type="text" @click="deleteById(row.id)">删除</el-button>
</template>
</el-table-column>
</ai-table>
</template>
</ai-list>
<ai-dialog
title="网格范围"
:visible.sync="showMap"
:customFooter="true"
:destroyOnClose="true"
border
width="850px"
>
<div class="map">
<div class="tipinput">
<el-input
v-if="editRow.plottingStatus == 0"
v-model="searchAddress"
@change="addressChange"
clearable
placeholder="请输入关键字"
id="tipinput"
size="medium"
style="width: 200px"
></el-input>
</div>
<div id="panel" v-if="editRow.plottingStatus == 0"></div>
<div class="container" id="container"></div>
<el-button-group
style="margin-top: 8px"
v-if="editRow.plottingStatus == 1"
>
<el-button type="primary" size="mini" @click="beginPoltting()"
>开始编辑</el-button
>
<el-button size="mini" @click="finishPoltting()">结束编辑</el-button>
</el-button-group>
<el-button-group
style="margin-top: 8px"
v-if="editRow.plottingStatus == 0"
>
<el-button size="mini" @click="draw('polygon')"
>开始绘制多边形</el-button
>
<!-- <el-button size="mini" @click="close()">关闭绘制</el-button> -->
<el-button size="mini" @click="clear()">清除绘制</el-button>
</el-button-group>
</div>
<div class="dialog-footer" slot="footer">
<el-button size="medium" @click="showMap = false">取消</el-button>
<el-button type="primary" size="medium" @click="confirm()"
>确认</el-button
>
</div>
<ai-dialog :title="`${gridInfo.girdName}网格成员`" :visible.sync="dialog" customFooter @closed="gridInfo={}"
width="700px">
<ai-table :tableData="gridInfo.tableData" :colConfigs="gridMemberColConfigs" :dict="dict"
:isShowPagination="false" :show-header="false"/>
<template #footer>
<el-button @click="dialog=false">关闭</el-button>
</template>
</ai-dialog>
</div>
</section>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader";
import MapPlotting from "./mapPlotting";
export default {
name: "List",
components: {MapPlotting},
label: "网格区块",
props: {
instance: Function,
@@ -223,167 +181,95 @@ export default {
path: [],
overlays: [],
isEdit: false,
searchId: "",
fileList: [],
location: {}
dialog: false,
gridInfo: {},
gridMemberColConfigs: [
{prop: "name"},
{prop: "checkType", formart: v => v === '1' ? '网格员' : '网格长'}
]
};
},
created() {
this.getTreeList();
this.getList();
this.getCorpLocation()
this.dict.load("girdLevel", "girdType", "isLastLevel", "plottingStatus");
this.dict.load("girdType", "isLastLevel", "plottingStatus", "girdMemberType");
},
computed: {
colConfigs() {
let _ = this;
return [
{ type: 'selection'},
{
prop: "girdName",
align: "left",
label: "网格名称",
},
{
prop: "girdCode",
align: "center",
label: "网格编码",
},
{
prop: "girdType",
align: "center",
label: "网格类型",
render(h, { row }) {
return h("span", {}, _.dict.getLabel("girdType", row.girdType) || '-');
},
},
{
prop: "girdLevel",
align: "center",
label: "网格层级",
render(h, { row }) {
return h("span", {}, _.dict.getLabel("girdLevel", row.girdLevel) || '-');
},
},
{
prop: "plottingStatus",
align: "center",
label: "标绘状态",
render(h, { row }) {
return h(
"span",
{
style: {
color: _.dict.getColor("plottingStatus", row.plottingStatus),
},
},
_.dict.getLabel("plottingStatus", row.plottingStatus)
);
},
},
{
prop: "createTime",
align: "center",
label: "创建时间",
render(h, { row }) {
return h("span", {}, row.createTime.substring(0, 11));
},
},
{
prop: "girdMemberNames",
align: "center",
width: 200,
label: "网格员",
},
{type: 'selection'},
{prop: "girdName", align: "left", label: "网格名称",},
{slot: 'user'},
{prop: "plottingStatus", align: "center", label: "标绘状态", dict: "plottingStatus"},
{prop: "createTime", align: "center", label: "创建时间"},
{slot: "options"}
];
},
isTopGrid() {
return this.info.id == this.treeObj.treeList?.[0]?.id
}
},
methods: {
getCorpLocation(){
this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res=>{
if(res.code==0){
this.location = res.data
}
})
},
handleNodeClick(val) {
this.info = { ...val };
this.searchId = val.id;
this.info = this.$copy(val);
this.getList();
},
getTreeList() {
this.instance
.post("/app/appgirdinfo/listByTop", null, null)
.then((res) => {
if (res.code == 0) {
this.treeObj.treeList = [...res.data];
this.info = { ...this.treeObj.treeList[0] };
this.$nextTick(() => {
this.treeObj.treeList.length && this.$refs.tree.setCurrentKey(this.treeObj.treeList[0].id)
})
}
});
this.instance.post("/app/appgirdinfo/listAllByTop").then(res => {
if (res?.data) {
this.treeObj.treeList = [res.data];
this.info = res.data
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.info.id)
})
}
});
},
filterNode(value, data) {
if (!value) return true;
return data.girdName.indexOf(value) !== -1;
},
deleteById(ids) {
ids &&
this.$confirm("是否要删除该网格区块", {
type: "error",
})
.then(() => {
this.instance
.post("/app/appgirdinfo/delete", null, {
params: { ids },
})
.then((res) => {
if (res?.code == 0) {
this.$message.success("删除成功!");
this.getList();
}
});
})
.catch(() => {});
},
deleteTree(ids) {
ids &&
this.$confirm("是否要删除该网格区块", {
type: "error",
})
.then(() => {
this.instance
.post("/app/appgirdinfo/delete", null, {
params: { ids },
})
.then((res) => {
if (res?.code == 0) {
this.$message.success("删除成功!");
this.getTreeList();
}
});
})
.catch(() => {});
},
getList() {
this.instance
.post("/app/appgirdinfo/list", null, {
params: {
...this.searchObj,
...this.page,
parentGirdId: this.info.girdLevel === '0' ? '' : this.searchId,
},
})
.then((res) => {
if (res?.data) {
this.tableData = res.data.records;
this.page.total = res.data.total;
ids && this.$confirm("删除网格后会清除网格内网格员的责任家庭信息如有下级网格会同步删除下级网格所有数据!", {
type: "error",
}).then(() => {
this.instance.post("/app/appgirdinfo/delete", null, {params: {ids}}).then((res) => {
if (res?.code == 0) {
this.$message.success("删除成功!");
this.getList();
this.getTreeList();
}
});
}).catch(() => 0);
},
deleteTree(ids) {
ids && this.$confirm("是否要删除该网格区块", {
type: "error",
}).then(() => {
this.instance.post("/app/appgirdinfo/delete", null, {
params: {ids}
}).then((res) => {
if (res?.code == 0) {
this.$message.success("删除成功!");
this.getTreeList();
}
});
}).catch(() => 0);
},
getList() {
this.instance.post("/app/appgirdinfo/list", null, {
params: {
...this.searchObj,
...this.page,
parentGirdId: this.isTopGrid ? '' : this.info.id,
},
}).then((res) => {
if (res?.data) {
this.tableData = res.data.records;
this.page.total = res.data.total;
}
});
},
handleSelectionChange(val) {
this.ids = [];
@@ -393,14 +279,13 @@ export default {
},
//添加二级网格
addTwoLevel() {
this.info = { ...this.treeObj.treeList[0] };
this.info = {...this.treeObj.treeList[0]};
this.toAdd()
},
toAdd() {
this.$emit('change', {
type: 'Add',
params: this.info,
isEdit: this.isEdit
let {id: parentGirdId, girdName: parentGirdName} = this.info
this.$router.push({
hash: "#add", query: {parentGirdId, parentGirdName}
})
},
goBack() {
@@ -410,165 +295,16 @@ export default {
this.getTreeList();
});
},
poltting(row) {
this.showMap = true;
this.editRow = { ...row };
AMapLoader.load({
key: "b553334ba34f7ac3cd09df9bc8b539dc", // 申请好的Web端开发者Key首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["AMap.PolygonEditor", "AMap.MouseTool", "AMap.PlaceSearch"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
AMapUI: {
// 是否加载 AMapUI缺省不加载
version: "1.1", // AMapUI 缺省 1.1
plugins: [], // 需要加载的 AMapUI ui插件
},
})
.then((AMap) => {
this.map = new AMap.Map("container", {
resizeEnable: true,
zoom: 14,
});
if (this.editRow.plottingStatus == 1) {
let path = [];
this.editRow.points.map((e, index) => {
path[index] = [e.lng, e.lat];
});
let polygon = new AMap.Polygon({
path: path,
strokeColor: "#FF33FF",
strokeWeight: 6,
strokeOpacity: 0.2,
fillOpacity: 0.4,
fillColor: "#1791fc",
zIndex: 50,
bubble: true,
});
this.map.add([polygon]);
this.map.setFitView();
this.polyEditor = new AMap.PolygonEditor(this.map, polygon);
} else {
this.mouseTool = new AMap.MouseTool(this.map);
this.placeSearch = new AMap.PlaceSearch({
pageSize: 3, // 单页显示结果条数
pageIndex: 1, // 页码
city: "", // 兴趣点城市
citylimit: false, //是否强制限制在设置的城市内搜索
map: this.map, // 展现结果的地图实例
panel: "panel", // 结果列表将在此容器中进行展示。
autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
});
this.map.setZoomAndCenter(14, [this.location.lng, this.location.lat], false, 600);
this.eventOn();
}
})
.catch((e) => {
console.log(e);
});
},
see(row) {
this.info = { ...row };
this.isEdit = true;
this.toAdd()
},
draw(type) {
switch (type) {
case "marker": {
this.mouseTool.marker({
//同Marker的Option设置
});
break;
}
case "polyline": {
this.mouseTool.polyline({
strokeColor: "#80d8ff",
//同Polyline的Option设置
});
break;
}
case "polygon": {
this.mouseTool.polygon({
fillColor: "#00b0ff",
strokeColor: "#80d8ff",
borderWeight: 2,
strokeWeight: 4,
//同Polygon的Option设置
});
break;
}
case "rectangle": {
this.mouseTool.rectangle({
fillColor: "#00b0ff",
strokeColor: "#80d8ff",
//同Polygon的Option设置
});
break;
}
case "circle": {
this.mouseTool.circle({
fillColor: "#00b0ff",
strokeColor: "#80d8ff",
//同Circle的Option设置
});
break;
}
}
showEdit(id) {
this.$router.push({hash: "#add", query: {id}})
},
//map搜索
addressChange(val) {
this.placeSearch.search(val);
},
close() {
this.mouseTool.close(true);
},
clear() {
this.map.remove(this.overlays);
this.overlays = [];
this.path = [];
},
beginPoltting() {
this.polyEditor.open();
},
finishPoltting() {
this.polyEditor.close();
},
confirm() {
let path = [];
if (this.editRow.plottingStatus == 1) {
this.polyEditor
.getTarget()
.getPath()
.map((e) => {
path.push({ lng: e.lng, lat: e.lat });
});
} else {
path = [...this.path];
}
delete this.editRow.points;
this.instance
.post(
`/app/appgirdinfo/addOrUpdate`,
{
...this.editRow,
points: path,
},
null
)
.then((res) => {
if (res.code == 0) {
this.getList();
this.showMap = false;
}
});
},
eventOn() {
this.path = [];
this.overlays = [];
this.map.on("mousemove", this.showInfoMove, this);
this.mouseTool.on("draw", ({ type, obj }) => {
obj.getPath().map((e) => {
this.path.push({ lat: e.getLat(), lng: e.getLng() });
});
this.overlays.push(obj);
confirm(row, points) {
this.instance.post(`/app/appgirdinfo/addOrUpdate`, {...row, points}).then((res) => {
if (res.code == 0) {
this.$message.success("提交成功!")
this.getList();
}
});
},
resetSearch() {
@@ -577,6 +313,19 @@ export default {
});
this.getList();
},
showGridMembers(row) {
if (row.girdMemberNumber > 0) {
this.gridInfo = this.$copy(row)
this.instance.post("/app/appgirdmemberinfo/listByGirdIdByThree", null, {
params: {girdId: row.id}
}).then(res => {
if (res?.data) {
this.gridInfo.tableData = res.data
this.dialog = true
}
})
} else this.$message.warning("当前网格无成员")
}
},
};
</script>
@@ -585,11 +334,12 @@ export default {
.app-grid-block {
width: 100%;
height: 100%;
::v-deep .el-tree {
background: transparent;
.el-tree-node__expand-icon.is-leaf {
color: transparent!important;
color: transparent !important;
}
.el-tree-node__content > .el-tree-node__expand-icon {
@@ -616,52 +366,60 @@ export default {
}
.is-current > .el-tree-node__content {
color: #fff !important;
&:hover {
background: #2266FF;
color: #fff;
}
background: #2266FF;
span {
.el-tooltip {
color: #fff;
}
}
}
.flex-box {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
& > div {
display: flex;
}
}
.mt10 {
padding: 8px 0;
}
.map {
width: 780px;
position: relative;
overflow: hidden;
::v-deep.fullscreenMap {
.el-dialog {
display: flex;
flex-direction: column;
.container {
width: 760px;
height: 420px;
border-radius: 2px;
border: 1px solid #d0d4dc;
}
.el-dialog__body {
padding: 0;
flex: 1;
min-height: 0;
#panel {
position: absolute;
height: 400px;
right: 30px;
top: 20px;
width: 280px;
overflow: hidden;
z-index: 10000;
}
.ai-dialog__content {
max-height: unset !important;
padding-bottom: 0;
height: 100%;
.tipinput {
position: absolute;
width: 200px;
height: 38px;
left: 20px;
top: 20px;
z-index: 10000;
.ai-dialog__content--wrapper {
padding-right: 0 !important;
}
}
}
}
}

View File

@@ -0,0 +1,233 @@
<template>
<section class="mapPlotting">
<div class="clicker" @click="dialog=true,$emit('open')">
<slot v-if="$slots.default"/>
<el-button v-else type="text">标绘</el-button>
</div>
<ai-dialog :title="title" class="fullscreenMap"
:visible.sync="dialog"
:destroyOnClose="true"
@close="points=[]"
border fullscreen
@open="initMap" :modal="false"
@onConfirm="$emit('change',points.flat()),dialog=false">
<div class="mapPanel">
<div class="tipinput">
<el-input
v-model="searchAddress"
@change="addressChange"
clearable
placeholder="请输入关键字"
id="tipinput"
size="medium"/>
</div>
<div id="panel"/>
<div class="container fill" id="container"/>
<div class="operationBtns" v-if="map">
<el-alert type="success" title="操作说明:" :closable="false">
<li>1.双击覆盖物即可编辑</li>
<li>2.编辑状态,对点双击可删除该点</li>
<li>3.绘制状态,右键结束绘制</li>
<li>4.结束编辑才能保存绘制的覆盖物信息</li>
</el-alert>
<el-button-group>
<el-button type="primary" @click="handleAdd">新建</el-button>
<el-button @click="polyEditor.close()">结束编辑</el-button>
<el-button @click="clear()">清除绘制</el-button>
</el-button-group>
</div>
</div>
</ai-dialog>
</section>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader";
import {mapState} from "vuex";
export default {
name: "mapPlotting",
model: {
prop: "value",
event: "change"
},
props: {
title: {default: "地图标绘"},
value: Array
},
computed: {
...mapState(['user']),
},
data() {
return {
map: null,
polyEditor: null,
placeSearch: null,
searchAddress: "",
overlays: [],
points: [],
dialog: false
}
},
methods: {
addressChange(val) {
this.placeSearch.search(val);
},
clear() {
this.map.remove(this.overlays);
this.overlays = [];
this.points = []
},
handleAdd() {
if (this.points?.length == 0) {
let {polyEditor} = this
polyEditor.close();
polyEditor.setTarget();
polyEditor.open();
} else this.$message.error("请先清除已标绘图形!")
},
initMap() {
setTimeout(() => AMapLoader.load({
key: "b553334ba34f7ac3cd09df9bc8b539dc", // 申请好的Web端开发者Key首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["AMap.PlaceSearch", "AMap.PolygonEditor"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
AMapUI: {
// 是否加载 AMapUI缺省不加载
version: "1.1", // AMapUI 缺省 1.1
plugins: [], // 需要加载的 AMapUI ui插件
},
}).then((AMap) => {
this.map = new AMap.Map("container", {
resizeEnable: true,
});
this.placeSearch = new AMap.PlaceSearch({
pageSize: 5, // 单页显示结果条数
pageIndex: 1, // 页码
city: this.user.info.areaId?.substring(0, 6), // 兴趣点城市
citylimit: true, //是否强制限制在设置的城市内搜索
map: this.map, // 展现结果的地图实例
panel: "panel", // 结果列表将在此容器中进行展示。
autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
});
this.polyEditor = new AMap.PolygonEditor(this.map).on('add', ({target}) => {
this.polyEditor.addAdsorbPolygons(target)
target.on("dblclick", () => {
this.polyEditor.setTarget(target);
this.polyEditor.open()
})
})
this.polyEditor.on('end', ({target}) => {
if (target) {
this.overlays.push(target);
this.points = target.getPath().map(e => ({lat: e.getLat(), lng: e.getLng()}))
}
});
if (this.value?.length > 0) {
let path = this.value.map(e => [e.lng, e.lat]);
let polygon = new AMap.Polygon({
path,
strokeColor: "#FF33FF",
strokeWeight: 6,
strokeOpacity: 0.2,
fillOpacity: 0.4,
fillColor: "#1791fc",
})
this.map.add([polygon]);
this.map.setFitView();
this.polyEditor.addAdsorbPolygons(polygon)
polygon.on('dblclick', () => {
this.polyEditor.setTarget(polygon);
this.polyEditor.open()
});
this.polyEditor.setTarget(polygon);
this.polyEditor.open()
} else {
this.map.setCity(this.user.info.areaId?.substring(0, 6))
this.map.setZoom(14, false, 600)
}
}), 500)
}
}
}
</script>
<style lang="scss" scoped>
.mapPlotting {
display: inline-block;
text-align: left;
.clicker {
display: inline-block;
}
.mapPanel {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
.container {
width: inherit;
}
#panel {
position: absolute;
height: 400px;
right: 30px;
top: 20px;
width: 280px;
overflow: hidden;
z-index: 10000;
}
.tipinput {
position: absolute;
width: 300px;
height: 38px;
left: 20px;
top: 20px;
z-index: 10000;
}
.operationBtns {
position: absolute;
left: 20px;
bottom: 20px;
z-index: 10000;
}
}
::v-deep.fullscreenMap {
.el-dialog {
display: flex;
flex-direction: column;
.el-dialog__body {
padding: 0;
flex: 1;
min-height: 0;
.ai-dialog__content {
max-height: unset !important;
padding-bottom: 0;
height: 100%;
.ai-dialog__content--wrapper {
padding-right: 0 !important;
}
}
}
}
}
::v-deep .amap-copyright {
display: none !important;
}
::v-deep .amap-logo {
display: none !important;
}
}
</style>

View File

@@ -13,15 +13,20 @@
</header>
<div class="tree-div">
<el-tree
:data="treeObj.treeList"
:props="treeObj.defaultProps"
@node-click="handleNodeClick"
node-key="id"
ref="tree"
:expand-on-click-node="false"
:filter-node-method="filterNode"
default-expand-all
highlight-current>
:data="treeObj.treeList"
:props="treeObj.defaultProps"
@node-click="handleNodeClick"
node-key="id"
ref="tree"
:expand-on-click-node="false"
:filter-node-method="filterNode"
default-expand-all
highlight-current>
<template slot-scope="{node,data}">
<el-tooltip :content="node.label">
<div class="el-tree-node__label" v-text="node.label"/>
</el-tooltip>
</template>
</el-tree>
</div>
</div>
@@ -33,295 +38,289 @@
</div>
</template>
<script>
import {mapState} from 'vuex'
import {mapState} from 'vuex'
export default {
name: 'AppGridMap',
label: "网格地图",
props: {
instance: Function,
dict: Object,
permissions: Function,
},
data() {
return {
map: null,
mapLib: null,
show: true,
retryMapCount: 0,
polygons: [],
export default {
name: 'AppGridMap',
label: "网格地图",
props: {
instance: Function,
dict: Object,
permissions: Function,
},
data() {
return {
map: null,
mapLib: null,
show: true,
retryMapCount: 0,
polygons: [],
drawer: false,
filterText: "",
treeObj: {
treeList: [],
defaultProps: {
children: "girdList",
label: "girdName",
},
defaultExpandedKeys: [],
drawer: false,
filterText: "",
treeObj: {
treeList: [],
defaultProps: {
children: "girdList",
label: "girdName",
},
ops: {},
defaultExpandedKeys: [],
},
ops: {},
path: [],
searchObj: {
onlineStatus: "",
girdMemberName: "",
},
member: {
memberList: [],
},
currInfo: {},
infoWindowHtml: "",
marker: {},
activeId: null,
labels: []
};
path: [],
searchObj: {
onlineStatus: "",
girdMemberName: "",
},
member: {
memberList: [],
},
currInfo: {},
infoWindowHtml: "",
marker: {},
activeId: null,
labels: []
};
},
computed: {
...mapState(['user']),
},
created() {
this.dict.load("onlineStatus")
this.getTreeList().then(() => {
this.getLeafNodes()
})
},
watch: {
filterText(val) {
this.$refs.tree.filter(val);
},
computed: {
...mapState(['user']),
},
methods: {
filterNode(value, data) {
if (!value) return true;
return data.girdName.indexOf(value) !== -1;
},
created() {
this.dict.load("onlineStatus")
this.getTreeList().then(() => {
this.getLeafNodes()
getTreeList() {
return this.instance.post(`/app/appgirdinfo/listAll`).then((res) => {
if (res.code == 0) {
this.treeObj.treeList = res.data;
this.$nextTick(() => {
res.data.length && this.$refs.tree.setCurrentKey(res.data[0].id)
})
}
})
},
watch: {
filterText(val) {
this.$refs.tree.filter(val);
},
onMapInit() {
this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res => {
if (res.code === 0) {
this.map.setCenter(new this.mapLib.LatLng(res.data.lat, res.data.lng))
}
})
},
methods: {
filterNode(value, data) {
if (!value) return true;
return data.girdName.indexOf(value) !== -1;
},
getTreeList() {
return this.instance.post(`/app/appgirdinfo/listAll`).then((res) => {
if (res.code == 0) {
this.treeObj.treeList = res.data;
this.$nextTick(() => {
res.data.length && this.$refs.tree.setCurrentKey(res.data[0].id)
})
}
})
},
onMapInit () {
this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res=>{
if (res.code === 0) {
this.map.setCenter(new this.mapLib.LatLng(res.data.lat, res.data.lng))
}
})
},
getLeafNodes() {
this.instance.post(`/app/appgirdinfo/listAll2`).then((res) => {
if (res?.data) {
const arr = res.data.map(v => {
return {
id: v.id,
girdName: v.girdName,
points: v.points ? v.points.map(p => [p.lng, p.lat]) : []
}
}).filter(v => v.points.length)
this.renderGridMap(arr)
}
})
},
handleNodeClick (val) {
if (val.girdLevel === '0') {
this.getLeafNodes()
return false
}
this.instance.post(`/app/appgirdinfo/queryChildGirdInfoByGirdId?girdId=${val.id}`).then((res) => {
if (res?.data) {
const arr = res.data.map(v => {
return {
id: v.id,
girdName: v.girdName,
points: v.points ? v.points.map(p => [p.lng, p.lat]) : []
}
}).filter(v => v.points.length)
if (!arr.length) {
return this.$message.error('该网格还未标绘')
getLeafNodes() {
this.instance.post(`/app/appgirdinfo/listAll2`).then((res) => {
if (res?.data) {
const arr = res.data.map(v => {
return {
id: v.id,
girdName: v.girdName,
points: v.points ? v.points.map(p => [p.lng, p.lat]) : []
}
}).filter(v => v.points.length)
this.renderGridMap(arr)
}
})
},
fitBounds(latLngList, count = 0) {
let {mapLib: TMap} = this
if (TMap) {
if (latLngList.length === 0) {
return null;
}
let boundsN = latLngList[0].getLat();
let boundsS = boundsN;
let boundsW = latLngList[0].getLng();
let boundsE = boundsW;
latLngList.forEach((point) => {
point.getLat() > boundsN && (boundsN = point.getLat());
point.getLat() < boundsS && (boundsS = point.getLat());
point.getLng() > boundsE && (boundsE = point.getLng());
point.getLng() < boundsW && (boundsW = point.getLng());
});
return new TMap.LatLngBounds(
new TMap.LatLng(boundsS, boundsW),
new TMap.LatLng(boundsN, boundsE)
);
} else {
if (count < 5) {
this.fitBounds(latLngList, ++count)
}
this.renderGridMap(arr)
}
},
})
},
handleNodeClick(val) {
this.instance.post(`/app/appgirdinfo/queryChildGirdInfoByGirdId?girdId=${val.id}`).then((res) => {
if (res?.data) {
const arr = res.data.map(v => {
return {
id: v.id,
girdName: v.girdName,
points: v.points ? v.points.map(p => [p.lng, p.lat]) : []
}
}).filter(v => v.points.length)
renderGridMap(paths) {
let {map, mapLib: TMap } = this
if (TMap) {
if (this.polygons.length > 0) {
this.polygons.forEach(e => e.destroy())
this.labels.forEach(e => {
e.destroy(e.id)
})
this.polygons = []
this.labels = []
if (!arr.length) {
return this.$message.error('该网格还未标绘')
}
if (paths?.length > 0) {
let bounds = []
paths.forEach((path, i) => {
let polygon = new TMap.MultiPolygon({
map, styles: {
default: new TMap.PolygonStyle({
showBorder: true,
borderColor: '#5088FF',
borderWidth: 2,
color: this.$colorUtils.Hex2RGBA('#5088FF', 0.1)
})
},
id: path.id,
geometries: [{paths: path.points.map(e => new TMap.LatLng(e[1], e[0]))}]
})
this.polygons.push(polygon)
bounds.push(this.fitBounds(path.points.map(e => new TMap.LatLng(e[1], e[0]))))
polygon.on('click', e => {
// const id = e.target.id
// this.getGridInfo(id)
})
this.renderGridMap(arr)
}
})
},
const points = path.points.map(e => new TMap.LatLng(e[1], e[0]))
var position = TMap.geometry.computeCentroid(points)
let label = new TMap.MultiLabel({
id: `label~${path.id}`,
data: path.id,
map: map,
styles: {
building: new TMap.LabelStyle({
color: '#3777FF',
size: 20,
alignment: 'center',
verticalAlignment: 'middle'
})
},
geometries: [
{
id: `label-class-${i}`,
styleId: 'building',
position: position,
content: path.girdName,
}
]
})
this.labels.push(label)
label.on('click', e => {
// this.getGridInfo(e.target.id.split('~')[1])
});
})
bounds = bounds.reduce((a, b) => {
return this.fitBounds([
a.getNorthEast(),
a.getSouthWest(),
b.getNorthEast(),
b.getSouthWest(),
]);
});
map.fitBounds(bounds, {padding: 100})
}
fitBounds(latLngList, count = 0) {
let {mapLib: TMap} = this
if (TMap) {
if (latLngList.length === 0) {
return null;
}
},
hasClass(ele, cls) {
return ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
},
addClass(ele, cls) {
if (!this.hasClass(ele, cls)) ele.className += " " + cls;
},
removeClass(ele, cls) {
if (this.hasClass(ele, cls)) {
const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
ele.className = ele.className.replace(reg, " ");
}
},
changClass(ele, className) {
if (!this.hasClass(ele, className)) {
this.addClass(ele, className);
} else {
this.removeClass(ele, className);
}
},
percentage() {
if (this.member.onlineNumber == 0) {
return 0;
} else {
return (
100 *
(this.member.onlineNumber / this.member.allMemberNumber)
).toFixed(2);
}
},
getMemberList() {
this.instance.post(`/app/appgirdmemberinfo/queryGirdMemberByMap`, this.searchObj).then((res) => {
if (res.code == 0) {
let markers = [];
this.member = res.data;
this.member.memberList.map((e) => {
if (e.onlineStatus == "1") {
markers.push({lng: e.lng, lat: e.lat, name: e.name});
}
});
this.initMap(null, null, markers);
}
let boundsN = latLngList[0].getLat();
let boundsS = boundsN;
let boundsW = latLngList[0].getLng();
let boundsE = boundsW;
latLngList.forEach((point) => {
point.getLat() > boundsN && (boundsN = point.getLat());
point.getLat() < boundsS && (boundsS = point.getLat());
point.getLng() > boundsE && (boundsE = point.getLng());
point.getLng() < boundsW && (boundsW = point.getLng());
});
},
clickMember(marker) {
if (marker.onlineStatus == 1) {
this.activeId = marker.id;
this.marker = marker;
this.infoWindowContent(marker);
return new TMap.LatLngBounds(
new TMap.LatLng(boundsS, boundsW),
new TMap.LatLng(boundsN, boundsE)
);
} else {
if (count < 5) {
this.fitBounds(latLngList, ++count)
}
},
infoWindowContent(marker) {
this.instance
.post(`/app/location/xyToAddress`, null, {
params: {
x: marker.lat,
y: marker.lng,
},
})
.then((res) => {
if (res.code == 0) {
this.infoWindowHtml = `<div class="info">
}
},
renderGridMap(paths) {
let {map, mapLib: TMap} = this
if (TMap) {
if (this.polygons.length > 0) {
this.polygons.forEach(e => e.destroy())
this.labels.forEach(e => {
e.destroy(e.id)
})
this.polygons = []
this.labels = []
}
if (paths?.length > 0) {
let bounds = []
paths.forEach((path, i) => {
let polygon = new TMap.MultiPolygon({
map, styles: {
default: new TMap.PolygonStyle({
showBorder: true,
borderColor: '#5088FF',
borderWidth: 2,
color: this.$colorUtils.Hex2RGBA('#5088FF', 0.1)
})
},
id: path.id,
geometries: [{paths: path.points.map(e => new TMap.LatLng(e[1], e[0]))}]
})
this.polygons.push(polygon)
bounds.push(this.fitBounds(path.points.map(e => new TMap.LatLng(e[1], e[0]))))
polygon.on('click', e => {
// const id = e.target.id
// this.getGridInfo(id)
})
const points = path.points.map(e => new TMap.LatLng(e[1], e[0]))
var position = TMap.geometry.computeCentroid(points)
let label = new TMap.MultiLabel({
id: `label~${path.id}`,
data: path.id,
map: map,
styles: {
building: new TMap.LabelStyle({
color: '#3777FF',
size: 20,
alignment: 'center',
verticalAlignment: 'middle'
})
},
geometries: [
{
id: `label-class-${i}`,
styleId: 'building',
position: position,
content: path.girdName,
}
]
})
this.labels.push(label)
label.on('click', e => {
// this.getGridInfo(e.target.id.split('~')[1])
});
})
bounds = bounds.reduce((a, b) => {
return this.fitBounds([
a.getNorthEast(),
a.getSouthWest(),
b.getNorthEast(),
b.getSouthWest(),
]);
});
map.fitBounds(bounds, {padding: 100})
}
}
},
hasClass(ele, cls) {
return ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
},
addClass(ele, cls) {
if (!this.hasClass(ele, cls)) ele.className += " " + cls;
},
removeClass(ele, cls) {
if (this.hasClass(ele, cls)) {
const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
ele.className = ele.className.replace(reg, " ");
}
},
changClass(ele, className) {
if (!this.hasClass(ele, className)) {
this.addClass(ele, className);
} else {
this.removeClass(ele, className);
}
},
percentage() {
if (this.member.onlineNumber == 0) {
return 0;
} else {
return (
100 *
(this.member.onlineNumber / this.member.allMemberNumber)
).toFixed(2);
}
},
getMemberList() {
this.instance.post(`/app/appgirdmemberinfo/queryGirdMemberByMap`, this.searchObj).then((res) => {
if (res.code == 0) {
let markers = [];
this.member = res.data;
this.member.memberList.map((e) => {
if (e.onlineStatus == "1") {
markers.push({lng: e.lng, lat: e.lat, name: e.name});
}
});
this.initMap(null, null, markers);
}
});
},
clickMember(marker) {
if (marker.onlineStatus == 1) {
this.activeId = marker.id;
this.marker = marker;
this.infoWindowContent(marker);
}
},
infoWindowContent(marker) {
this.instance
.post(`/app/location/xyToAddress`, null, {
params: {
x: marker.lat,
y: marker.lng,
},
})
.then((res) => {
if (res.code == 0) {
this.infoWindowHtml = `<div class="info">
<p>
<span class="name">${marker.name}</span>
<span class="lat">${marker.lng},${marker.lat}</span>
@@ -333,31 +332,31 @@
<span class="iconfont iconarea" id="addressSpan">当日轨迹</span>
</p>
</div>`;
this.initMap(false, marker);
}
});
},
queryTrajectory() {
this.instance
.post(`/app/appgirdmembertrajectory/queryTrajectory`, null, {
params: {
userId: this.marker.userId,
},
})
.then((res) => {
if (res.code == 0) {
let path = [];
if (res.data) {
res.data.map((e, index) => {
path[index] = [e.lng, e.lat];
});
}
this.initMap(path, this.marker);
}
});
},
this.initMap(false, marker);
}
});
},
}
queryTrajectory() {
this.instance
.post(`/app/appgirdmembertrajectory/queryTrajectory`, null, {
params: {
userId: this.marker.userId,
},
})
.then((res) => {
if (res.code == 0) {
let path = [];
if (res.data) {
res.data.map((e, index) => {
path[index] = [e.lng, e.lat];
});
}
this.initMap(path, this.marker);
}
});
},
},
}
</script>
<style lang="scss" scoped>

View File

@@ -1,27 +1,7 @@
<template>
<ai-list class="AppGridMember" v-if="!isShowDetail">
<template slot="title">
<ai-title title="网格员管理" :isShowBottomBorder="false"></ai-title>
</template>
<template slot="tabs">
<el-tabs v-model="currIndex">
<el-tab-pane v-for="(tab,i) in tabs" :key="i" :label="tab.label">
<component :ref="String(i)" v-if="currIndex == i" :is="tab.comp" @change="onChange" lazy :instance="instance"
:dict="dict" :permissions="permissions"/>
</el-tab-pane>
</el-tabs>
</template>
</ai-list>
<Add v-else-if="component === 'Add'" :params="params" :instance="instance" :dict="dict" :permissions="permissions"
@change="onChange"></Add>
<Family v-else-if="component === 'Family'" :params="params" :instance="instance" :dict="dict"
:permissions="permissions" @change="onChange"></Family>
<MonitorUser v-else-if="component === 'MonitorUser'" :params="params" :instance="instance" :dict="dict"
:permissions="permissions" @change="onChange"></MonitorUser>
<ApplyDetail v-else-if="component === 'ApplyDetail'" :params="params" :instance="instance" :dict="dict"
:permissions="permissions" @change="onChange"></ApplyDetail>
<ApplyAdd v-else-if="component === 'ApplyAdd'" :params="params" :instance="instance" :dict="dict"
:permissions="permissions" @change="onChange"></ApplyAdd>
<keep-alive include="GmList">
<component :is="currentPage" v-bind="$props" @change="onChange"/>
</keep-alive>
</template>
<script>
@@ -32,39 +12,29 @@ import ApplyDetail from './components/ApplyDetail'
import ApplyAdd from './components/ApplyAdd'
import Family from './components/Family'
import MonitorUser from './components/MonitorUser'
import GmList from "./components/gmList";
export default {
name: "AppGridMember",
label: "网格管理员",
props: {
instance: Function,
dict: Object,
permissions: Function
},
data() {
return {
component: "List",
params: {},
include: [],
currIndex: '0',
isShowDetail: false
};
},
computed: {
tabs() {
return [
{label: '网格员信息', name: 'List', comp: List, permission: ''},
{label: '申报信息', name: 'ApplyList', comp: ApplyList, permission: 'app_appgirdmemberapply_detail'}
].filter(item => {
return item.name !== 'ApplyList' || this.permissions(item.permission)
})
currentPage() {
let {hash} = this.$route
return hash == "#Family" ? Family :
hash == "#MonitorUser" ? MonitorUser :
hash == "#Add" ? Add :
hash == "#ApplyAdd" ? ApplyAdd :
hash == "#ApplyDetail" ? ApplyDetail :
GmList
}
},
components: {
GmList,
Add,
List,
Family,
@@ -74,51 +44,11 @@ export default {
ApplyAdd
},
mounted() {
},
methods: {
onChange(data) {
if (data.type === "Add") {
this.component = "Add"
this.isShowDetail = true
this.params = data.params
}
if (data.type === "Family") {
this.component = "Family"
this.isShowDetail = true
this.params = data.params
}
if (data.type === "MonitorUser") {
this.component = "MonitorUser"
this.isShowDetail = true
this.params = data.params
}
if (data.type === "ApplyDetail") {
this.component = "ApplyDetail"
this.isShowDetail = true
this.params = data.params
}
if (data.type === "ApplyAdd") {
this.component = "ApplyAdd"
this.isShowDetail = true
this.params = data.params
}
if (data.type === "list") {
this.component = "List"
this.isShowDetail = false
this.params = data.params
}
if (data.type === "ApplyList") {
this.component = "ApplyList"
this.isShowDetail = false
this.params = data.params
}
let {type, params: query} = data,
hash = ["ApplyList", "list"].includes(type) ? "" : "#" + type
this.$router.push({hash, query})
}
}
}

View File

@@ -1,7 +1,7 @@
<template>
<ai-detail class="content-add">
<template slot="title">
<ai-title :title="params.id ? '编辑' : '添加'" isShowBack isShowBottomBorder @onBackClick="cancel(false)">
<ai-title :title="$route.query.id ? '编辑' : '添加'" isShowBack isShowBottomBorder @onBackClick="cancel(false)">
</ai-title>
</template>
<template slot="content">
@@ -35,7 +35,6 @@
props: {
instance: Function,
dict: Object,
params: Object
},
data () {
@@ -51,9 +50,9 @@
},
created () {
if (this.params && this.params.id) {
this.id = this.params.id
this.getInfo(this.params.id)
if ( this.$route.query.id) {
this.id = this.$route.query.id
this.getInfo(this.$route.query.id)
}
},
@@ -76,7 +75,7 @@
this.isLoading = true
this.instance.post(`/app/appgirdmemberapply/addOrUpdate`, {
...this.form,
id: this.params.id || ''
id: this.$route.query.id || ''
}).then(res => {
if (res.code == 0) {
this.$message.success('提交成功')

View File

@@ -19,46 +19,45 @@
</template>
<script>
export default {
name: 'ApplyDetail',
export default {
name: 'ApplyDetail',
props: {
instance: Function,
dict: Object,
params: Object
props: {
instance: Function,
dict: Object,
},
data() {
return {
info: {},
id: ''
}
},
created() {
if (this.$route.query.id) {
this.id = this.$route.query.id
this.getInfo(this.$route.query.id)
}
},
methods: {
getInfo(id) {
this.instance.post(`/app/appgirdmemberapply/queryDetailById?id=${id}`).then(res => {
if (res.code === 0) {
this.info = res.data
}
})
},
data () {
return {
info: {},
id: ''
}
},
created () {
if (this.params && this.params.id) {
this.id = this.params.id
this.getInfo(this.params.id)
}
},
methods: {
getInfo (id) {
this.instance.post(`/app/appgirdmemberapply/queryDetailById?id=${id}`).then(res => {
if (res.code === 0) {
this.info = res.data
}
})
},
cancel (isRefresh) {
this.$emit('change', {
type: 'ApplyList',
isRefresh: !!isRefresh
})
}
cancel(isRefresh) {
this.$emit('change', {
type: 'ApplyList',
isRefresh: !!isRefresh
})
}
}
}
</script>
<style scoped lang="scss">

View File

@@ -144,18 +144,14 @@
add (id) {
this.$emit('change', {
type: 'ApplyAdd',
params: {
id: id || ''
}
params: {id}
})
},
toDetail (id) {
this.$emit('change', {
type: 'ApplyDetail',
params: {
id
}
params: {id}
})
},
@@ -176,4 +172,4 @@
</script>
<style lang="scss" scoped>
</style>
</style>

View File

@@ -6,40 +6,40 @@
<template slot="content">
<ai-search-bar class="search-bar">
<template #left>
<el-button size="small" type="primary" icon="iconfont iconAdd" @click="isShow = true">添加</el-button>
<el-button size="small" type="primary" icon="iconfont iconAdd" @click="dialog=true">添加</el-button>
<el-button size="small" :disabled="!ids.length" icon="iconfont iconDelete" @click="removeAll">批量删除</el-button>
<el-select size="small" style="width: 200px;" v-model="search.girdId" placeholder="所属网格" clearable @change="getListInit()">
<el-option
v-for="(item,i) in girdList"
:key="i"
:label="item.girdName"
:value="item.id"
v-for="(item,i) in girdList"
:key="i"
:label="item.girdName"
:value="item.id"
>
</el-option>
</el-select>
</template>
<template #right>
<el-input
v-model="search.name"
class="search-input"
size="small"
v-throttle="() => {search.current = 1, getList()}"
placeholder="姓名/身份证/联系方式"
clearable
@clear="search.current = 1, search.name = '', getList()"
suffix-icon="iconfont iconSearch">
v-model="search.name"
class="search-input"
size="small"
v-throttle="() => {search.current = 1, getList()}"
placeholder="姓名/身份证/联系方式"
clearable
@clear="search.current = 1, search.name = '', getList()"
suffix-icon="iconfont iconSearch">
</el-input>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
style="margin-top: 6px;"
:current.sync="search.current"
:size.sync="search.size"
@handleSelectionChange="handleSelectionChange"
@getList="getList">
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
style="margin-top: 6px;"
:current.sync="search.current"
:size.sync="search.size"
@handleSelectionChange="handleSelectionChange"
@getList="getList">
<el-table-column slot="options" width="100px" fixed="right" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
@@ -49,451 +49,174 @@
</el-table-column>
</ai-table>
<ai-dialog
:visible.sync="isShow"
width="890px"
@close="closeDialog"
title="添加户主"
@onConfirm="onConfirm">
<ai-area-select clearable always-show :instance="instance" v-model="areaId" :disabled-level="disabledLevel" @change="search.current = 1, getUserList()"></ai-area-select>
<span style="margin-top:16px;"><span style="color:#f46;margin-right:4px;">*</span>网格</span>
<el-select size="small" style="width: 280px;margin-top:16px;" v-model="girdId" placeholder="请选择网格" clearable>
<el-option
v-for="(item,i) in girdList"
:key="i"
:label="item.girdName"
:value="item.id"
>
</el-option>
</el-select>
<div class="AiWechatSelecter-container">
<div class="AiWechatSelecter-container__left" v-loading="isLoading">
<div class="AiWechatSelecter-header">
<div class="AiWechatSelecter-header__left">
<h2>户主信息列表</h2>
</div>
<el-input
class="search-input"
size="mini"
placeholder="请输入姓名/身份证号"
v-model="name"
clearable
@keyup.enter.native="getUserList()"
@clear="name = '', getUserList()"
suffix-icon="iconfont iconSearch">
</el-input>
</div>
<el-scrollbar class="AiWechatSelecter-list">
<el-checkbox-group v-model="chooseUser">
<el-checkbox
:label="`${item.name}~${item.id}`"
v-for="(item, index) in userList"
:key="index">
{{ item.name }}-{{ item.idNumber }}
</el-checkbox>
</el-checkbox-group>
<AiEmpty v-if="!this.userList.length"></AiEmpty>
</el-scrollbar>
</div>
<div class="AiWechatSelecter-container__right">
<div class="AiWechatSelecter-header AiWechatSelecter-header__right">
<h2>已选择</h2>
<el-button size="mini" icon="el-icon-delete" @click="clearAll">清空</el-button>
</div>
<el-scrollbar class="AiWechatSelecter-list">
<div class="tags-wrapper">
<el-tag
v-for="(item, index) in chooseUser"
:key="index"
closable
@close="del(item)"
size="small"
type="info">
{{ item.split('~')[0] }}
</el-tag>
</div>
</el-scrollbar>
</div>
</div>
:visible.sync="dialog"
width="1100px"
@close="closeDialog"
title="添加户主"
@onConfirm="onConfirm">
<el-form ref="DialogForm" size="small" label-width="0">
<el-form-item>
<ai-area-select clearable always-show :instance="instance" v-model="areaId" :disabled-level="disabledLevel"/>
</el-form-item>
<el-form-item label="网格:" required label-width="80px">
<el-select size="small" v-model="girdId" placeholder="请选择网格" clearable>
<el-option v-for="(item,i) in girdList" :key="i" :label="item.girdName" :value="item.id"/>
</el-select>
</el-form-item>
<el-form-item>
<ai-table-select :instance="instance" :action="`/app/appresident/list?householdName=1&areaId=${areaId||''}&auditStatus=1`"
@select="v=>chooseUser=v" multiple/>
</el-form-item>
</el-form>
</ai-dialog>
</template>
</ai-list>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'Family',
import {mapState} from 'vuex'
props: {
instance: Function,
dict: Object,
params: Object
},
export default {
name: 'Family',
props: {
instance: Function,
dict: Object,
},
data() {
return {
search: {
current: 1,
size: 10,
name: '',
girdId: ''
},
isLoading: false,
form: {
},
userList: [],
data() {
return {
search: {
current: 1,
size: 10,
name: '',
chooseUser: [],
isShow: false,
total: 10,
colConfigs: [
{ type: 'selection', label: '' },
{ prop: 'name', label: '户主姓名', align: 'left', width: '200px' },
{ prop: 'idNumber', label: '身份证号', align: 'center' },
{ prop: 'phone', label: '联系方式', align: 'center' },
{ prop: 'girdName', label: '所属网格', align: 'center' },
{ prop: 'createTime', label: '添加时间', align: 'center' },
{ slot: 'options', label: '操作', align: 'center' }
],
tableData: [],
areaId: '',
ids: [],
disabledLevel: 0,
girdList: [],
girdId: '',
}
},
girdId: ''
},
isLoading: false,
form: {},
chooseUser: [],
dialog: false,
total: 10,
colConfigs: [
{type: 'selection', label: ''},
{prop: 'name', label: '户主姓名', align: 'left', width: '200px'},
{prop: 'idNumber', label: '身份证号', align: 'center'},
{prop: 'phone', label: '联系方式', align: 'center'},
{prop: 'girdName', label: '所属网格', align: 'center'},
{prop: 'createTime', label: '添加时间', align: 'center'},
{slot: 'options', label: '操作', align: 'center'}
],
tableData: [],
areaId: '',
ids: [],
disabledLevel: 0,
girdList: [],
girdId: '',
}
},
computed: {
...mapState(['user'])
computed: {
...mapState(['user'])
},
created() {
this.areaId = this.user.info.areaId || ""
this.disabledLevel = this.user.info.areaList?.length || 0
this.getGirdList()
this.getList()
this.dict.load('epidemicDangerousAreaLevel')
},
methods: {
getGirdList() {
this.instance.post(`/app/appgirdmemberinfo/queryMyGirdListByLevel2?girdMemberId=${this.$route.query.id}`).then(res => {
if (res.code == 0) {
this.girdList = res.data
}
})
},
created() {
this.areaId = this.user.info.areaId
this.disabledLevel = this.user.info.areaList.length
this.dict.load('epidemicDangerousAreaLevel').then(() => {
this.getGirdList()
this.getList()
this.getUserList()
getListInit() {
this.search.current = 1
this.getList()
},
getList() {
this.instance.post(`/app/appgirdmemberresident/listByGirdMember`, null, {
params: {
...this.search,
girdMemberId: this.$route.query.id,
areaId: this.areaId
}
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
},
methods: {
getGirdList() {
this.instance.post(`/app/appgirdmemberinfo/queryMyGirdListByLevel2?girdMemberId=${this.params.id}`).then(res => {
if (res.code == 0) {
this.girdList = res.data
}
})
},
getListInit() {
this.search.current = 1
this.getList()
},
getList () {
this.instance.post(`/app/appgirdmemberresident/listByGirdMember`, null, {
params: {
...this.search,
girdMemberId: this.params.id,
areaId: this.areaId
}
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
},
removeAll() {
if (!this.ids) {
return this.$message.error('请选择户主')
}
this.remove(this.ids.join(','))
},
handleSelectionChange(e) {
this.ids = e.map(v => v.gmrId)
},
clearAll () {
this.chooseUser = []
},
onConfirm () {
if(!this.girdId) {
return this.$message.error('请选择网格')
}
if (!this.chooseUser.length) {
return this.$message.error('请选择户主')
}
const residentList = this.chooseUser.map(v => {
return {
girdMemberId: this.params.id,
name: v.split('~')[0],
residentId: v.split('~')[1],
girdId: this.girdId
}
})
this.instance.post(`/app/appgirdmemberresident/add`, {
residentList
}).then(res => {
if (res.code == 0) {
this.current = 1
this.getList()
this.$message.success('添加成功')
this.closeDialog()
}
})
},
closeDialog() {
this.isShow = false
this.chooseUser = []
this.girdId = ''
this.name = ''
this.areaId = this.user.info.areaId
this.getUserList()
},
del (e) {
this.chooseUser.splice(this.chooseUser.indexOf(e), 1)
},
getUserList () {
this.isLoading = true
this.instance.post(`/app/appresident/list`, null, {
params: {
current: 1,
size: 200,
con: this.name,
householdName: 1,
areaId: this.areaId,
}
}).then(res => {
if (res.code == 0) {
this.userList = res.data.records
}
this.isLoading = false
})
},
onBack () {
this.$emit('change', {
type: 'list'
})
},
remove(id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appgirdmemberresident/delete?ids=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
})
if (!this.ids) {
return this.$message.error('请选择户主')
}
this.remove(this.ids.join(','))
},
handleSelectionChange(e) {
this.ids = e.map(v => v.gmrId)
},
onConfirm() {
if (!this.girdId) {
return this.$message.error('请选择网格')
}
if (!this.chooseUser.length) {
return this.$message.error('请选择户主')
}
const residentList = this.chooseUser.map(v => {
return {
girdMemberId: this.$route.query.id,
name: v.name,
residentId: v.id,
girdId: this.girdId
}
})
this.instance.post(`/app/appgirdmemberresident/add`, {
residentList
}).then(res => {
if (res.code == 0) {
this.current = 1
this.getList()
this.$message.success('添加成功')
this.dialog = false
}
})
},
closeDialog() {
this.chooseUser = []
this.girdId = ''
this.areaId = this.user.info.areaId
},
del(e) {
this.chooseUser.splice(this.chooseUser.indexOf(e), 1)
},
onBack() {
this.$emit('change', {
type: 'list'
})
},
remove(id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appgirdmemberresident/delete?ids=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
})
}
}
}
</script>
<style lang="scss" scoped>
.Family {
.AiWechatSelecter-container {
display: flex;
height: 380px;
margin-top: 20px;
::v-deep {
.el-icon-circle-close {
display: inline-block!important;
}
}
.tree-container {
& > span {
display: block;
margin-bottom: 4px;
}
.tree-user__item {
display: flex;
align-items: center;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
img {
width: 27px;
height: 27px;
margin-right: 10px;
}
}
::v-deep .el-tree {
background: transparent;
.el-tree-node {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
}
.el-tree-node__content {
height: auto;
margin-top: 2px;
// align-items: inherit;
}
.el-tree-node__expand-icon {
height: 24px;
}
}
.mask-btn__wrapper {
position: relative;
}
.mask-btn {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.userlist-item {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
padding: 0 17px;
cursor: pointer;
user-select: none;
::v-deep .el-checkbox__label {
display: none;
}
.userlist-item__left {
display: flex;
align-items: center;
span {
color: #222222;
font-size: 14px;
}
img {
width: 40px;
height: 40px;
margin-right: 8px;
}
}
}
& > div {
width: 280px;
background: #FCFCFC;
border: 1px solid #D0D4DC;
}
.AiWechatSelecter-list {
height: calc(100% - 40px);
padding: 8px 0;
::v-deep .el-scrollbar__wrap {
margin-bottom: 0!important;
overflow-x: hidden;
}
::v-deep .el-checkbox-group {
padding: 0 8px;
.el-checkbox {
display: block;
margin-right: 0;
}
}
}
.AiWechatSelecter-container__left {
flex: 1;
}
.AiWechatSelecter-container__right {
flex: 1;
margin-left: 20px;
.AiWechatSelecter-list {
.tags-wrapper {
padding: 0 8px;
}
.el-tag {
margin: 0 8px 8px 0px;
color: #222222;
font-size: 14px;
}
}
}
.AiWechatSelecter-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 40px;
padding: 0 8px 0 0;
border-bottom: 1px solid #D0D4DC;
background: #F5F7FA;
.AiWechatSelecter-header__left {
display: flex;
align-items: center;
padding: 0 8px;
h2 {
height: 100%;
line-height: 40px;
color: #222222;
font-size: 14px;
text-align: center;
cursor: pointer;
border-bottom: 2px solid transparent;
&.active {
color: #2266FF;
border-color: #2266FF;
}
}
}
.el-button {
height: 28px;
padding: 7px 5px;
}
.el-input {
width: 160px;
}
}
.AiWechatSelecter-header__right {
padding: 0 8px;
h2 {
color: #222222;
font-size: 14px;
text-align: center;
}
}
}
}
.Family {
}
</style>

View File

@@ -51,71 +51,24 @@
</ai-table>
<ai-dialog
:visible.sync="isShow"
width="890px"
width="1100px"
@close="closeDialog"
title="添加户主"
@onConfirm="onConfirm">
<ai-area-select clearable always-show :instance="instance" v-model="areaId" :disabled-level="disabledLevel"
@change="search.current = 1, getUserList()"></ai-area-select>
<span style="margin-top:16px;"><span style="color:#f46;margin-right:4px;">*</span>网格</span>
<el-select size="small" style="width: 280px;margin-top:16px;" v-model="girdId" placeholder="请选择网格" clearable>
<el-option
v-for="(item,i) in girdList"
:key="i"
:label="item.girdName"
:value="item.id"
>
</el-option>
</el-select>
<div class="AiWechatSelecter-container">
<div class="AiWechatSelecter-container__left" v-loading="isLoading">
<div class="AiWechatSelecter-header">
<div class="AiWechatSelecter-header__left">
<h2>户主信息列表</h2>
</div>
<el-input
class="search-input"
size="mini"
placeholder="请输入姓名/身份证号"
v-model="name"
clearable
v-throttle="getUserList"
@clear="name = '', getUserList()"
suffix-icon="iconfont iconSearch">
</el-input>
</div>
<el-scrollbar class="AiWechatSelecter-list">
<el-checkbox-group v-model="chooseUser">
<el-checkbox
:label="`${item.name}~${item.id}`"
v-for="(item, index) in userList"
:key="index">
{{ item.name }}-{{ item.idNumber }}
</el-checkbox>
</el-checkbox-group>
<AiEmpty v-if="!this.userList.length"></AiEmpty>
</el-scrollbar>
</div>
<div class="AiWechatSelecter-container__right">
<div class="AiWechatSelecter-header AiWechatSelecter-header__right">
<h2>已选择</h2>
<el-button size="mini" icon="el-icon-delete" @click="clearAll">清空</el-button>
</div>
<el-scrollbar class="AiWechatSelecter-list">
<div class="tags-wrapper">
<el-tag
v-for="(item, index) in chooseUser"
:key="index"
closable
@close="del(item)"
size="small"
type="info">
{{ item.split('~')[0] }}
</el-tag>
</div>
</el-scrollbar>
</div>
</div>
<el-form ref="DialogForm" size="small" label-width="0">
<el-form-item>
<ai-area-select clearable always-show :instance="instance" v-model="areaId" :disabled-level="disabledLevel"/>
</el-form-item>
<el-form-item label="网格:" required label-width="80px">
<el-select size="small" v-model="girdId" placeholder="请选择网格" clearable>
<el-option v-for="(item,i) in girdList" :key="i" :label="item.girdName" :value="item.id"/>
</el-select>
</el-form-item>
<el-form-item>
<ai-table-select :instance="instance" :action="`/app/apppreventionreturntopoverty/list?isHousehold=1&&areaId=${areaId}&auditStatus=1`"
@select="v=>chooseUser=v" multiple/>
</el-form-item>
</el-form>
</ai-dialog>
</template>
</ai-list>
@@ -130,7 +83,6 @@ export default {
props: {
instance: Function,
dict: Object,
params: Object
},
data() {
@@ -141,9 +93,7 @@ export default {
name: '',
girdId: ''
},
isLoading: false,
form: {},
userList: [],
name: '',
chooseUser: [],
isShow: false,
@@ -176,13 +126,12 @@ export default {
this.dict.load('epidemicDangerousAreaLevel').then(() => {
this.getGirdList()
this.getList()
this.getUserList()
})
},
methods: {
getGirdList() {
this.instance.post(`/app/appgirdmemberinfo/queryMyGirdListByLevel2?girdMemberId=${this.params.id}`).then(res => {
this.instance.post(`/app/appgirdmemberinfo/queryMyGirdListByLevel2?girdMemberId=${this.$route.query.id}`).then(res => {
if (res.code == 0) {
this.girdList = res.data
}
@@ -196,7 +145,7 @@ export default {
this.instance.post(`/app/appgirdmemberpoverty/listByGirdMemberByWeb`, null, {
params: {
...this.search,
girdMemberId: this.params.id,
girdMemberId: this.$route.query.id,
}
}).then(res => {
if (res.code == 0) {
@@ -215,11 +164,6 @@ export default {
handleSelectionChange(e) {
this.ids = e.map(v => v.gmpId)
},
clearAll() {
this.chooseUser = []
},
onConfirm() {
if (!this.girdId) {
return this.$message.error('请选择网格')
@@ -231,10 +175,10 @@ export default {
const povertyList = this.chooseUser.map(v => {
return {
girdMemberId: this.params.id,
name: v.split('~')[0],
girdMemberId: this.$route.query.id,
name: v.name,
girdId: this.girdId,
povertyId: v.split('~')[1]
povertyId: v.id
}
})
this.instance.post(`/app/appgirdmemberpoverty/add`, {
@@ -254,38 +198,12 @@ export default {
this.girdId = ''
this.name = ''
this.areaId = this.user.info.areaId
this.getUserList()
},
del(e) {
this.chooseUser.splice(this.chooseUser.indexOf(e), 1)
},
getUserList() {
this.isLoading = true
this.instance.post(`/app/apppreventionreturntopoverty/list`, null, {
params: {
current: 1,
size: 200,
con: this.name,
isHousehold: 1,
areaId: this.areaId
}
}).then(res => {
if (res.code == 0) {
this.userList = res.data.records
}
this.isLoading = false
})
},
onBack() {
this.$emit('change', {
type: 'list'
})
},
remove(ids) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appgirdmemberpoverty/delete`, null, {

View File

@@ -6,22 +6,23 @@
</template>
<template #content>
<el-form
ref="rules"
:model="forms"
:rules="formRules"
size="small"
label-suffix=""
label-width="136px">
<ai-card title="基础信息" >
<template #right v-if="title=='网格员详情'">
ref="rules"
:model="forms"
:rules="formRules"
size="small"
label-suffix=""
label-width="136px">
<ai-card title="基础信息">
<template #right v-if="title=='网格员详情'">
<span style="color:#2266FF;cursor: pointer;font-size: 12px;" class="iconfont iconEdit" v-if="editOne==false" @click="editOne=true">修改</span>
<span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editOne==true" @click="searchDetail(),editOne=false">取消</span>
<span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editOne==true"
@click="searchDetail(),editOne=false">取消</span>
<span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editOne==true" @click="save()">保存</span>
</template>
<template slot="content">
<div class="above" v-if="editOne==true">
<div class="left">
<el-form-item label="网格员姓名" prop="name" >
<el-form-item label="网格员姓名" prop="name">
<el-input v-model="forms.name" placeholder="请选择网格员" disabled>
<template #append>
<ai-wechat-selecter :isMultiple="false" refs="addTags" :instance="instance" v-model="users" @change="getSelectPerson">
@@ -30,30 +31,20 @@
</template>
</el-input>
</el-form-item>
<el-form-item label="选用日期" prop="selectionDate" >
<el-date-picker
v-model="forms.selectionDate"
type="date"
style="width: 100%"
value-format="yyyy-MM-dd"
size="medium"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
<el-form-item label="身份证号" prop="idNumber" >
<el-input v-model="forms.idNumber" placeholder="请输入…" maxlength="18" show-word-limit></el-input>
<el-form-item label="身份证号" prop="idNumber">
<el-input v-model="forms.idNumber" placeholder="请输入…" maxlength="18" show-word-limit></el-input>
</el-form-item>
</div>
<div class="right">
<el-form-item label="照片" prop="photo">
<!-- <ai-uploader :instance="instance" v-model="photoList" :limit="1" @change="photoChange"></ai-uploader> -->
<ai-avatar :instance="instance" v-model="forms.photo"/>
<ai-avatar :instance="instance" v-model="forms.photo"/>
</el-form-item>
</div>
</div>
<div class="above" v-if="editOne==true">
<div class="left">
<el-form-item label="出生日期" prop="birthday" >
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
v-model="forms.birthday"
type="date"
@@ -63,70 +54,71 @@
placeholder="选择日期">
</el-date-picker>
</el-form-item>
<el-form-item label="联系电话" prop="phone" >
<el-form-item label="联系电话" prop="phone">
<el-input v-model.number="forms.phone" placeholder="请输入…" maxlength="11" show-word-limit></el-input>
</el-form-item>
</div>
<div class="right">
<el-form-item label="性别" prop="sex" >
<el-form-item label="性别" prop="sex">
<el-select size="medium" style="width: 100%" v-model="forms.sex" placeholder="请选择..." clearable>
<el-option
v-for="(item,i) in dict.getDict('sex')"
:key="i"
:label="item.dictName"
:value="item.dictValue"
v-for="(item,i) in dict.getDict('sex')"
:key="i"
:label="item.dictName"
:value="item.dictValue"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="电子邮箱" prop="mail" >
<el-input v-model="forms.mail" placeholder="请输入…"></el-input>
<el-form-item label="电子邮箱" prop="mail">
<el-input v-model="forms.mail" placeholder="请输入…"></el-input>
</el-form-item>
</div>
</div>
<template v-if="editOne==false">
<template v-if="editOne==false">
<div class="above">
<div class="left">
<ai-wrapper label-width="120px" :columnsNumber="1" style="margin-top: 16px;">
<ai-info-item label="网格员姓名:"><span >{{forms.name}}</span></ai-info-item>
<ai-info-item label="选用日期"><span >{{forms.selectionDate}}</span></ai-info-item>
<ai-info-item label="身份证号"><span >{{forms.idNumber}}</span></ai-info-item>
<ai-info-item label="性别"><span >{{dict.getLabel('sex', forms.sex)}}</span></ai-info-item>
<ai-info-item label="出生日期"><span >{{forms.birthday}}</span></ai-info-item>
<ai-info-item label="电子邮箱:"><span >{{forms.mail}}</span></ai-info-item>
<ai-wrapper label-width="120px" :columnsNumber="1" style="margin-top: 16px;">
<ai-info-item label="网格员姓名:"><span>{{ forms.name }}</span></ai-info-item>
<ai-info-item label="身份证号"><span>{{ forms.idNumber }}</span></ai-info-item>
<ai-info-item label="性别"><span>{{ dict.getLabel('sex', forms.sex) }}</span></ai-info-item>
<ai-info-item label="出生日期"><span>{{ forms.birthday }}</span></ai-info-item>
<ai-info-item label="电子邮箱"><span>{{ forms.mail }}</span></ai-info-item>
</ai-wrapper>
</div>
<div class="right">
<ai-wrapper label-width="120px" :columnsNumber="1" style="margin-top: 16px;">
<ai-wrapper label-width="120px" :columnsNumber="1" style="margin-top: 16px;">
<ai-info-item label="照片:" v-if="forms.photo">
<span >
<span>
<ai-uploader :instance="instance" v-model="photoList" disabled :limit="1" @change="photoChange"></ai-uploader>
</span>
</ai-info-item>
<ai-info-item label="联系电话:"><span >{{forms.phone}}</span></ai-info-item>
<ai-info-item label="联系电话:"><span>{{ forms.phone }}</span></ai-info-item>
</ai-wrapper>
</div>
</div>
</template>
</template>
</ai-card>
<ai-card title="关联信息" >
<template #right v-if="title=='网格员详情'">
<ai-card title="关联信息">
<template #right v-if="title=='网格员详情'">
<span style="color:#2266FF;cursor: pointer;font-size: 12px;" class="iconfont iconEdit" v-if="editTwo==false" @click="editTwo=true">修改</span>
<span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editTwo==true" @click="searchDetail(),editTwo=false">取消</span>
<span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editTwo==true"
@click="searchDetail(),editTwo=false">取消</span>
<span style="color:#2266FF;margin-left: 16px;cursor: pointer;font-size: 12px;" v-if="editTwo==true" @click="save()">保存</span>
</template>
<template slot="content">
<template v-if="editTwo==true">
<el-form-item label="责任网格" prop="girdInfoList" style="margin-top: 8px;">
<el-form-item style="width: 100%" label-width="80px" :label="'网格' + (index + 1)" v-for="(item, index) in forms.girdInfoList" :key="'选项' + (index + 1)">
<el-form-item style="width: 100%" label-width="80px" :label="'网格' + (index + 1)" v-for="(item, index) in forms.girdInfoList"
:key="'选项' + (index + 1)">
<div class="form-flex">
<el-select v-model="item.checkType" placeholder="请选择网格角色">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-input disabled v-model="item.girdName" :maxlength="200" size="small" placeholder="请选择责任网格">
@@ -142,13 +134,13 @@
</el-form-item>
<div class="above">
<div class="left">
<el-form-item label="是否特殊网格员" prop="isGirdMember" >
<el-form-item label="是否特殊网格员" prop="isGirdMember">
<el-radio-group v-model="forms.isGirdMember">
<el-radio label="0"></el-radio>
<el-radio label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="政治面貌" prop="politicsStatus" >
<el-form-item label="政治面貌" prop="politicsStatus">
<el-select v-model="forms.politicsStatus" size="small" style="width: 100%" placeholder="请选择..." clearable>
<el-option v-for="(item,i) in dict.getDict('politicsStatus')" :key="i" :label="item.dictName" :value="item.dictValue"></el-option>
</el-select>
@@ -160,31 +152,31 @@
<el-option v-for="(item,i) in dict.getDict('girdMemberType')" :key="i" :label="item.dictName" :value="item.dictValue"></el-option>
</el-select>
</el-form-item>
<el-form-item label="学历" prop="education" >
<el-form-item label="学历" prop="education">
<el-select v-model="forms.education" style="width: 100%" size="small" placeholder="请选择..." clearable>
<el-option v-for="(item,i) in dict.getDict('education')" :key="i" :label="item.dictName" :value="item.dictValue"></el-option>
</el-select>
</el-form-item>
</div>
</div>
<el-form-item label="个人简介" prop="introduction" >
<el-form-item label="个人简介" prop="introduction">
<el-input
type="textarea"
maxlength="200"
show-word-limit
:rows="4"
placeholder="请输入内容"
v-model="forms.introduction">
type="textarea"
maxlength="200"
show-word-limit
:rows="4"
placeholder="请输入内容"
v-model="forms.introduction">
</el-input>
</el-form-item>
<el-form-item label="人生格言" prop="motto" >
<el-form-item label="人生格言" prop="motto">
<el-input
type="textarea"
maxlength="200"
show-word-limit
:rows="4"
placeholder="请输入内容"
v-model="forms.motto">
type="textarea"
maxlength="200"
show-word-limit
:rows="4"
placeholder="请输入内容"
v-model="forms.motto">
</el-input>
</el-form-item>
</template>
@@ -194,39 +186,40 @@
<ai-info-item label="是否特殊网格员:">
<span>{{ !forms.isGirdMember ? '-' : forms.isGirdMember === '0' ? '否' : '是' }}</span>
</ai-info-item>
<ai-info-item label="特殊网格员:" v-if="forms.isGirdMember==1"><span >{{dict.getLabel('girdMemberType', forms.girdMemberType)}}</span></ai-info-item>
<ai-info-item label="政治面貌:"><span >{{dict.getLabel('politicsStatus', forms.politicsStatus)}}</span></ai-info-item>
<ai-info-item label="学历"><span >{{dict.getLabel('education', forms.education)}}</span></ai-info-item>
<ai-info-item label="人生格言:" style="width: 100%;"><span >{{forms.motto}}</span></ai-info-item>
<ai-info-item label="个人简介" style="width: 100%;"><span >{{forms.introduction}}</span></ai-info-item>
<ai-info-item label="特殊网格员:" v-if="forms.isGirdMember==1"><span>{{ dict.getLabel('girdMemberType', forms.girdMemberType) }}</span>
</ai-info-item>
<ai-info-item label="政治面貌"><span>{{ dict.getLabel('politicsStatus', forms.politicsStatus) }}</span></ai-info-item>
<ai-info-item label="学历:"><span>{{ dict.getLabel('education', forms.education) }}</span></ai-info-item>
<ai-info-item label="人生格言" style="width: 100%;"><span>{{ forms.motto }}</span></ai-info-item>
<ai-info-item label="个人简介:" style="width: 100%;"><span>{{ forms.introduction }}</span></ai-info-item>
</ai-wrapper>
</template>
</template>
</ai-card>
</el-form>
<ai-dialog title="选择网格" :visible.sync="showGrid" :customFooter="true" :destroyOnClose="true" border width="720px">
<ai-dialog title="选择网格" :visible.sync="showGrid" :customFooter="true" :destroyOnClose="true" border width="720px">
<div class="grid">
<el-tree
:data="treeObj.treeList"
:props="treeObj.defaultProps"
node-key="id"
ref="tree"
:check-strictly="true"
show-checkbox
:default-checked-keys="currCheckedKeys"
default-expand-all
@check="onCheckChange">
:data="treeObj.treeList"
:props="treeObj.defaultProps"
node-key="id"
ref="tree"
:check-strictly="true"
show-checkbox
:default-checked-keys="currCheckedKeys"
default-expand-all
@check="onCheckChange">
</el-tree>
</div>
<div class="dialog-footer" slot="footer" >
<el-button size="medium" @click="showGrid=false">取消</el-button>
<el-button type="primary" size="medium" @click="getCheckedTree()">确认</el-button>
<div class="dialog-footer" slot="footer">
<el-button size="medium" @click="showGrid=false">取消</el-button>
<el-button type="primary" size="medium" @click="getCheckedTree()">确认</el-button>
</div>
</ai-dialog>
</template>
<template #footer v-if="title=='添加网格员'">
<el-button @click="cancel(false)" class="delete-btn footer-btn" > </el-button>
<el-button type="primary" @click="save()" class="footer-btn"> </el-button>
<el-button @click="cancel(false)" class="delete-btn footer-btn"> </el-button>
<el-button type="primary" @click="save()" class="footer-btn"> </el-button>
</template>
</ai-detail>
</section>
@@ -239,7 +232,6 @@ export default {
instance: Function,
dict: Object,
permissions: Function,
params: Object,
},
data() {
return {
@@ -290,7 +282,7 @@ export default {
},
created() {
this.beforeSelectTree()
if (this.params.id) {
if (this.$route.query.id) {
this.searchDetail();
this.title = "网格员详情";
this.editOne = false;
@@ -302,7 +294,7 @@ export default {
}
},
computed: {
currCheckedKeys () {
currCheckedKeys() {
if (this.forms && this.forms.girdInfoList && this.forms.girdInfoList[this.currIndex] && this.forms.girdInfoList[this.currIndex].id) {
return [this.forms.girdInfoList[this.currIndex].id]
}
@@ -324,14 +316,11 @@ export default {
};
return {
name: [
{ required: true, message: "请输入网格员姓名", trigger: "change" },
{required: true, message: "请输入网格员姓名", trigger: "change"},
],
selectionDate: [
{ required: true, message: "请选择选用日期", trigger: "change" },
],
phone: [{ required: true, validator: phonePass, trigger: "blur" }],
phone: [{required: true, validator: phonePass, trigger: "blur"}],
girdInfoList: [
{ required: true, message: "请选择责任网络", trigger: "change" },
{required: true, message: "请选择责任网络", trigger: "change"},
],
mail: [
{
@@ -344,14 +333,14 @@ export default {
},
},
methods: {
cancel (isRefresh) {
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh,
})
},
onCheckChange (e) {
onCheckChange(e) {
this.$nextTick(() => {
this.$refs.tree.getCheckedKeys().forEach(v => {
this.$refs.tree.setChecked(v, false)
@@ -360,11 +349,11 @@ export default {
})
},
removeGrid (index) {
removeGrid(index) {
this.forms.girdInfoList.splice(index, 1)
},
addGrid () {
addGrid() {
this.forms.girdInfoList.push({
id: '',
girdName: '',
@@ -375,10 +364,13 @@ export default {
this.forms.photo = val[0].url;
},
getSelectPerson(val) {
this.forms.name = val[0].name;
this.forms.phone = val[0].phone;
this.forms.userId = val[0].sysUserId
this.forms.wxUserId = val[0].id
if (val.length) {
this.forms.name = val[0].name;
this.forms.phone = val[0].phone;
this.forms.userId = val[0].sysUserId
this.forms.wxUserId = val[0].id
this.$refs.rules.validateField('name')
}
},
getCheckedTree() {
if (!this.$refs.tree.getCheckedNodes().length) {
@@ -423,17 +415,9 @@ export default {
if (!currInfo.id) {
return this.$message.error('请选择网格')
}
if (currInfo.checkType === '1' && currInfo.girdLevel !== '2') {
return this.$message.error(`一级、二级网格不能添加网格员`)
}
if (sameInfo.length) {
return this.$message.error('不能选择同一网格重复绑定')
}
}
this.instance.post(`/app/appgirdmemberinfo/addOrUpdate`,{
this.instance.post(`/app/appgirdmemberinfo/addOrUpdate`, {
...this.forms,
girdInfoListStr: this.forms.girdInfoList.map(v => v.girdName).join(',')
}).then((res) => {
@@ -453,31 +437,30 @@ export default {
});
},
searchDetail() {
this.instance
.post(`/app/appgirdmemberinfo/queryDetailById`, null, {
params: { id: this.params.id },
})
.then((res) => {
if (res.code == 0) {
this.forms = {
...res.data,
girdInfoList: res.data.girdInfoList || []
};
this.users = [{
name: res.data.name,
phone: res.data.phone,
userId: res.data.id,
id: res.data.wxUserId
}]
this.girdInfoStr = ''
this.photoList = [{ url: this.forms.photo }];
if (res.data.girdInfoList) {
res.data.girdInfoList.forEach((e) => {
this.girdInfoStr = this.girdInfoStr + `${e.checkType === '1' ? '网格员' : '网格长'}-${e.girdName}&emsp;`
})
}
let {id} = this.$route.query
this.instance.post(`/app/appgirdmemberinfo/queryDetailById`, null, {
params: {id}
}).then((res) => {
if (res.code == 0) {
this.forms = {
...res.data,
girdInfoList: res.data.girdInfoList || []
};
this.users = [{
name: res.data.name,
phone: res.data.phone,
userId: res.data.id,
id: res.data.wxUserId
}]
this.girdInfoStr = ''
this.photoList = [{url: this.forms.photo}];
if (res.data.girdInfoList) {
res.data.girdInfoList.forEach((e) => {
this.girdInfoStr = this.girdInfoStr + `${e.checkType === '1' ? '网格员' : '网格长'}-${e.girdName}&emsp;`
})
}
});
}
});
},
},
};
@@ -487,26 +470,28 @@ export default {
.add {
height: 100%;
.form-flex {
display: flex;
align-items: center;
.form-flex {
display: flex;
align-items: center;
& > .el-button {
margin-left: 20px;
}
.el-input {
width: 300px;
margin-left: 20px;
}
::v-deep .el-form-item__content {
margin-left: 0!important;
}
& > .el-button {
margin-left: 20px;
}
.el-input {
width: 300px;
margin-left: 20px;
}
::v-deep .el-form-item__content {
margin-left: 0 !important;
}
}
.ai-detail__title {
background-color: #fff;
}
.ai-detail__content {
.ai-detail__content--wrapper {
.el-form {
@@ -516,9 +501,11 @@ export default {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.el-form-item {
width: 48%;
}
.buildingTypes {
width: 100%;
}
@@ -526,16 +513,20 @@ export default {
}
}
}
::v-deep .el-tag {
margin-right: 8px;
color: #333333;
}
.footer-btn {
width: 92px;
}
.above{
.above {
display: flex;
.left, .right{
.left, .right {
flex: 1;
}
}

View File

@@ -0,0 +1,55 @@
<template>
<section class="gmList">
<ai-list class="AppGridMember">
<template slot="title">
<ai-title title="网格员管理" :isShowBottomBorder="false"></ai-title>
</template>
<template slot="tabs">
<el-tabs v-model="currIndex">
<el-tab-pane v-for="(tab,i) in tabs" :key="i" :label="tab.label">
<component :ref="String(i)" v-if="currIndex == i" :is="tab.comp" lazy :instance="instance"
:dict="dict" :permissions="permissions" v-on="$listeners"/>
</el-tab-pane>
</el-tabs>
</template>
</ai-list>
</section>
</template>
<script>
import List from "./list";
import ApplyList from "./ApplyList";
export default {
name: "gmList",
props: {
instance: Function,
dict: Object,
permissions: Function
},
computed: {
tabs() {
return [
{label: '网格员信息', name: 'List', comp: List, permission: ''},
{label: '申报信息', name: 'ApplyList', comp: ApplyList, permission: 'app_appgirdmemberapply_detail'}
].filter(item => {
return item.name !== 'ApplyList' || this.permissions(item.permission)
})
}
},
data() {
return {
currIndex: '0',
}
},
methods: {},
created() {
}
}
</script>
<style lang="scss" scoped>
.gmList {
height: 100%;
}
</style>

View File

@@ -1,54 +1,43 @@
<template>
<ai-list class="list" isTabs>
<template slot="content">
<ai-search-bar bottomBorder>
<template slot="left">
<el-date-picker
v-model="searchObj.selectionDate"
type="date"
@change="(page.current = 1), getList()"
value-format="yyyy-MM-dd"
size="small"
placeholder="选用时间">
</el-date-picker>
</template>
<template slot="right">
<el-input
v-model="searchObj.name"
size="small"
placeholder="网格员/责任网格"
v-throttle="() => {page.current = 1, getList()}"
clearable
@clear="(searchObj.name = '', page.current = 1), getList()"
suffix-icon="iconfont iconSearch" />
</template>
</ai-search-bar>
<ai-search-bar style="padding: 16px 0 0">
<template slot="left">
<el-button
icon="iconfont iconAdd"
type="primary"
size="small"
@click="add('')"
>添加</el-button
icon="iconfont iconAdd"
type="primary"
size="small"
@click="add('')"
>添加
</el-button
>
<el-button
icon="iconfont iconDelete"
@click="deleteById(ids.join(','))"
:disabled="!Boolean(ids.length)"
>删除</el-button
icon="iconfont iconDelete"
@click="deleteById(ids.join(','))"
:disabled="!Boolean(ids.length)"
>删除
</el-button
>
</template>
<template slot="right">
<el-input
v-model="searchObj.name"
size="small"
placeholder="网格员/责任网格"
v-throttle="() => {page.current = 1, getList()}"
clearable
@clear="(searchObj.name = '', page.current = 1), getList()"
suffix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
ref="aitableex"
:current.sync="page.current"
:size.sync="page.size"
@selection-change="(v) => (ids = v.map((e) => e.id))"
@getList="getList()">
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
:current.sync="page.current"
:size.sync="page.size"
@selection-change="(v) => (ids = v.map((e) => e.id))"
@getList="getList()">
<el-table-column label="操作" slot="options" align="center" fixed="right" width="220">
<template slot-scope="{ row }">
<div class="table-options">
@@ -97,67 +86,42 @@ export default {
},
computed: {
colConfigs() {
let _ = this;
return [
{
type: "selection",
},
{
prop: "name",
label: "网格员姓名",
},
{
prop: "girdInfoListStr",
align: "center",
label: "责任网格",
},
{
prop: "phone",
align: "center",
label: "联系电话",
},
{
prop: "selectionDate",
align: "center",
label: "选用时间",
},
{type: "selection"},
{prop: "name", label: "网格员姓名"},
{prop: "girdInfoListStr", align: "center", label: "责任网格"},
{prop: "phone", align: "center", label: "联系电话"},
{prop: "createTime", align: "center", label: "创建时间"},
];
},
},
methods: {
getList() {
this.instance
.post("/app/appgirdmemberinfo/list", null, {
params: {
...this.searchObj,
...this.page,
},
})
.then((res) => {
if (res.code == 0) {
this.tableData = res.data.records;
this.page.total = res.data.total;
}
});
this.instance.post("/app/appgirdmemberinfo/list", null, {
params: {...this.searchObj, ...this.page}
}).then((res) => {
if (res?.data) {
this.tableData = res.data.records;
this.page.total = res.data.total;
}
})
},
deleteById(ids) {
ids &&
this.$confirm("是否要删除该网格员", {
type: "error",
ids && this.$confirm("是否要删除该网格员", {
type: "error",
}).then(() => {
this.instance
.post("/app/appgirdmemberinfo/delete", null, {
params: {ids},
})
.then(() => {
this.instance
.post("/app/appgirdmemberinfo/delete", null, {
params: { ids },
})
.then((res) => {
if (res?.code == 0) {
this.$message.success("删除成功!");
this.getList();
}
});
})
.catch(() => {});
.then((res) => {
if (res?.code == 0) {
this.$message.success("删除成功!");
this.getList();
}
});
})
.catch(() => 0);
},
add(id) {
this.$emit('change', {
@@ -167,8 +131,7 @@ export default {
}
})
},
toMonitorUser (id) {
toMonitorUser(id) {
this.$emit('change', {
type: 'MonitorUser',
params: {
@@ -176,8 +139,7 @@ export default {
}
})
},
toFamily (id) {
toFamily(id) {
this.$emit('change', {
type: 'Family',
params: {
@@ -185,7 +147,6 @@ export default {
}
})
},
handleSelectionChange(val) {
this.ids = [];
val.map((e) => {
@@ -197,7 +158,7 @@ export default {
this.searchObj[e] = "";
});
this.getList();
},
}
},
};
</script>

View File

@@ -20,7 +20,7 @@
</div>
<div class="search-result" v-if="isShowSearch && searchList.length">
<div class="search-result__item" v-for="(item, index) in searchList" :key="index"
@click="chooseCommunity(item)">
@click="chooseCommunity(item)">
<i class="search-icon iconfont iconLocation"></i>
<h2 v-if="type != 1">{{ item.residentName }}</h2>
<span v-if="type != 1">{{ item.createAddress }}</span>
@@ -42,23 +42,23 @@
<h2>户主信息</h2>
<div class="community-info__item">
<label>所属村</label>
<span>{{info.areaName}}</span>
<span>{{ info.areaName }}</span>
</div>
<div class="community-info__item">
<label>姓名</label>
<span style="color:#2266FF;">{{info.name}}</span>
<span style="color:#2266FF;">{{ info.name }}</span>
</div>
<div class="community-info__item">
<label>联系电话</label>
<span style="color:#2266FF;">{{info.phone}}</span>
<span style="color:#2266FF;">{{ info.phone }}</span>
</div>
<div class="community-info__item">
<label>性别</label>
<span>{{info.sex == 1 ? '男' : '女'}}</span>
<span>{{ info.sex == 1 ? '男' : '女' }}</span>
</div>
<div class="community-info__item">
<label>年龄</label>
<span>{{info.age}}</span>
<span>{{ info.age }}</span>
</div>
<div class="community-info__item bg-fff"></div>
</div>
@@ -66,22 +66,22 @@
<h2>宅基地信息</h2>
<div class="community-info__item">
<label>住宅建筑面积</label>
<span>{{info.liveBuildingArea}}</span>
<span>{{ info.liveBuildingArea }}</span>
</div>
<div class="community-info__item">
<label>建筑层数</label>
<span>{{info.buildingFloorNumber}}</span>
<span>{{ info.buildingFloorNumber }}</span>
</div>
<div class="community-info__item">
<label>建筑高度</label>
<span>{{info.buildingHeight}}m</span>
<span>{{ info.buildingHeight }}m</span>
</div>
</div>
<div class="community-info__wrapper" v-if="!info.name">
<h2>房屋信息</h2>
<div class="community-info__item">
<label>所属社区</label>
<span>{{ info.areaName}}</span>
<span>{{ info.areaName }}</span>
</div>
<div class="community-info__item">
<label>所属小区</label>
@@ -89,7 +89,7 @@
</div>
<div class="community-info__item">
<label>房屋类型</label>
<span>{{ dict.getLabel("communityBuildingType",info.buildingType) }}</span>
<span>{{ dict.getLabel("communityBuildingType", info.buildingType) }}</span>
</div>
<div class="community-info__item">
<label>楼长姓名</label>
@@ -97,27 +97,28 @@
</div>
<div class="community-info__item">
<label>楼长电话</label>
<span>{{ info.managerPhone}}</span>
<span>{{ info.managerPhone }}</span>
</div>
</div>
<div class="community-btn" v-if="!info.name">
<el-button icon="iconfont iconloudongmoxing" size="small"
@click="showStatistics=true; $router.push({query: {communityId: info.communityId, buildingId: info.id,unitNum:house ? house.unitNumber : 1,buildingNumber:info.buildingNumber}})">楼栋模型
@click="showStatistics=true; $router.push({query: {communityId: info.communityId, buildingId: info.id,unitNum:house ? house.unitNumber : 1,buildingNumber:info.buildingNumber}})">
楼栋模型
</el-button>
</div>
</div>
<div class="map-menu">
<div class="map-menu__item">
<div class="map-layers__wrapper">
<div class="map-layers">
<div class="map-layers__item" @click="switchLayer(false)"
:class="[!isImageMap ? 'map-layers__item-active' : '']">
:class="[!isImageMap ? 'map-layers__item-active' : '']">
<img src="https://cdn.cunwuyun.cn/AppCommunityMap/dz.png" alt="">
<div class="map-layers__item--tag" :class="[!isImageMap ? 'map-layers__item--tag-active' : '']">地图</div>
</div>
<div class="map-layers__item" @click="switchLayer(true)"
:class="[isImageMap ? 'map-layers__item-active' : '']">
:class="[isImageMap ? 'map-layers__item-active' : '']">
<img src="https://cdn.cunwuyun.cn/AppCommunityMap/yx.png" alt="">
<div class="map-layers__item--tag" :class="[isImageMap ? 'map-layers__item--tag-active' : '']">卫星</div>
</div>
@@ -158,6 +159,7 @@ export default {
data() {
return {
map: null,
mapLib: null,
community: '',
isShowLayer: false,
isShowSearch: false,
@@ -171,13 +173,13 @@ export default {
list: [],
areaList: [],
info: {},
resident:null,
resident: null,
satellite: null,
zoom: 11,
chooseBuildId: '',
buildList: [],
searchList: [],
house:null,
house: null,
center: [],
type: '',
typeList: [
@@ -222,7 +224,7 @@ export default {
},
created() {
this.dict.load('householdRelation','communityBuildingType')
this.dict.load('householdRelation', 'communityBuildingType')
},
mounted() {
@@ -232,12 +234,12 @@ export default {
},
methods: {
getCorpLocation(){
if(this.showStatistics) { //楼栋模型返回重新查询
getCorpLocation() {
if (this.showStatistics) { //楼栋模型返回重新查询
return
}
this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res=>{
if(res.code==0){
this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res => {
if (res.code == 0) {
this.initMap(res.data);
}
})
@@ -255,14 +257,14 @@ export default {
},
search() {
if(this.type === '') {
if (this.type === '') {
this.searchList = []
this.$message.error('请先选择房屋类型')
return
}
this.isShowArea = false
var url = '/app/appcommunityhouseinfo/queryHouseByName'
if(this.type == 1) {
if (this.type == 1) {
url = '/app/apphomesteadinfo/list'
}
this.instance.post(url, null, {
@@ -275,9 +277,9 @@ export default {
}).then(res => {
if (res.code === 0) {
var data = []
if(this.type == 1) {
if (this.type == 1) {
data = res.data.records
}else {
} else {
data = res.data
}
@@ -293,14 +295,14 @@ export default {
getBuildInfo(id, type) {
var url = `/app/apphomesteadinfo/queryDetailById?id=${id}`
if(type == 0) {
url= `/app/appcommunityhouseinfo/queryDetailByIdWithBuilding?buildId=${id}`
if (type == 0) {
url = `/app/appcommunityhouseinfo/queryDetailByIdWithBuilding?buildId=${id}`
}
this.instance.post(url).then(res => {
if (res.code === 0) {
if(type == 1) {
if (type == 1) {
this.info = res.data
}else {
} else {
this.info = res.data.build
this.resident = null;
}
@@ -312,10 +314,10 @@ export default {
},
chooseCommunity(item) {
if(item.name) { //宅基地
if(!item.lng || !item.lat) {
if (item.name) { //宅基地
if (!item.lng || !item.lat) {
return this.$message.error('未获取到该房屋坐标信息')
}else {
} else {
this.map.setZoomAndCenter(18, [item.lng, item.lat], false, 600)
this.info = item
this.$nextTick(() => {
@@ -323,35 +325,35 @@ export default {
this.isShowInfo = true
})
}
}else { //楼栋
this.instance.post(`/app/appcommunityhouseinfo/queryDetailByIdWithBuilding`,null,{
params:{
buildId:item.buildingId,
houseId:item.id,
residentId:item.residentId
}
}).then(res => {
if (res.code === 0) {
if (!res.data.build?.lng || !res.data.build?.lat) {
this.isShowInfo = true
this.isShowSearch = false
this.info = res.data.build;
return this.$message.error('未获取到该房屋坐标信息')
} else {
this.chooseBuildId = res.data.build.id
this.house = res.data.house
this.resident = res.data.resident;
}
this.map.setZoomAndCenter(18, [res.data.build?.lng, res.data.build?.lat], false, 600)
this.info = res.data.build
this.$nextTick(() => {
this.isShowSearch = false
this.isShowInfo = true
})
}
})
} else { //楼栋
this.instance.post(`/app/appcommunityhouseinfo/queryDetailByIdWithBuilding`, null, {
params: {
buildId: item.buildingId,
houseId: item.id,
residentId: item.residentId
}
}).then(res => {
if (res.code === 0) {
if (!res.data.build?.lng || !res.data.build?.lat) {
this.isShowInfo = true
this.isShowSearch = false
this.info = res.data.build;
return this.$message.error('未获取到该房屋坐标信息')
} else {
this.chooseBuildId = res.data.build.id
this.house = res.data.house
this.resident = res.data.resident;
}
this.map.setZoomAndCenter(18, [res.data.build?.lng, res.data.build?.lat], false, 600)
this.info = res.data.build
this.$nextTick(() => {
this.isShowSearch = false
this.isShowInfo = true
})
}
})
}
},
@@ -365,7 +367,7 @@ export default {
<p>${context.count}</p>
</div>
</div>`
let {mapLib: AMap} = this
let offset = new AMap.Pixel(-9, -9)
context.marker.setContent(el)
context.marker.setOffset(offset)
@@ -380,23 +382,23 @@ export default {
const buildId = context.data[0].id
let el = ''
var urlType = ''
if(context.data[0].communityName == context.data[0].buildingNumber) { //宅基地
if (context.data[0].communityName == context.data[0].buildingNumber) { //宅基地
urlType = 1
el = `<div class="mark" id="buildId-${buildId}" style="${buildId === this.chooseBuildId?'background-color:#2266FF':'background-color:#FF701A'}">
el = `<div class="mark" id="buildId-${buildId}" style="${buildId === this.chooseBuildId ? 'background-color:#2266FF' : 'background-color:#FF701A'}">
<div class="mark-contaienr">
<span>${context.data[0].areaName}</span>&nbsp;&nbsp;
<span>${context.data[0].communityName}</span>
</div>
<div class="arrow" style="${buildId === this.chooseBuildId?'border-top-color: #2266FF':'border-top-color:#FF701A'}"></div>
<div class="arrow" style="${buildId === this.chooseBuildId ? 'border-top-color: #2266FF' : 'border-top-color:#FF701A'}"></div>
</div>`
}else {
} else {
urlType = 0
el = `<div class="mark" id="buildId-${buildId}" style="${buildId === this.chooseBuildId?'background-color:#2266FF':''}">
el = `<div class="mark" id="buildId-${buildId}" style="${buildId === this.chooseBuildId ? 'background-color:#2266FF' : ''}">
<div class="mark-contaienr">
<span>${context.data[0].communityName}</span>&nbsp;&nbsp;
<span>${context.data[0].buildingNumber}栋</span>
</div>
<div class="arrow" style="${buildId === this.chooseBuildId?'border-top-color: #2266FF':''}"></div>
<div class="arrow" style="${buildId === this.chooseBuildId ? 'border-top-color: #2266FF' : ''}"></div>
</div>`
}
@@ -421,6 +423,7 @@ export default {
},
addMakert(points) {
let {mapLib: AMap} = this
new AMap.MarkerClusterer(this.map, points, {
gridSize: 60,
maxZoom: 15,
@@ -444,9 +447,9 @@ export default {
lnglat: [item.lng, item.lat],
id: item.id,
corpId: item.corpId,
areaName:item.areaName,
areaName: item.areaName,
buildingNumber: item.name || item.buildingNumber,
communityName:item.name || item.communityName,
communityName: item.name || item.communityName,
}
})
@@ -470,8 +473,8 @@ export default {
this.isImageMap = flag
},
initMap({lng,lat}) {
this.center = [lng,lat];
initMap({lng, lat}) {
this.center = [lng, lat];
AMapLoader.load({
key: 'b553334ba34f7ac3cd09df9bc8b539dc',
version: '2.0',
@@ -481,6 +484,7 @@ export default {
plugins: []
}
}).then((AMap) => {
this.mapLib = AMap
this.map = new AMap.Map('map', {
resizeEnable: true,
zooms: [6, 20],
@@ -507,7 +511,7 @@ export default {
width: 100%;
}
::v-deep .ai-list__content--right-wrapper{
::v-deep .ai-list__content--right-wrapper {
height: 100%;
margin: 0px !important;
background-color: transparent !important;
@@ -889,7 +893,7 @@ export default {
white-space: nowrap;
}
p:first-child{
p:first-child {
font-size: 14px;
}
@@ -901,7 +905,7 @@ export default {
}
}
::v-deep .mark{
::v-deep .mark {
user-select: none;
cursor: pointer;
height: 32px;
@@ -914,7 +918,7 @@ export default {
box-sizing: border-box;
padding: 0 12px;
.mark-contaienr{
.mark-contaienr {
color: white;
font-size: 14px;
position: relative;
@@ -926,7 +930,7 @@ export default {
justify-content: center;
}
.arrow{
.arrow {
position: absolute;
left: 50%;
transform: translateX(-50%);
@@ -1124,8 +1128,8 @@ export default {
}
}
.bg-fff{
background-color: #fff!important;
.bg-fff {
background-color: #fff !important;
}
}
}
@@ -1336,7 +1340,8 @@ export default {
color: #89B;
}
}
.map-area__right{
.map-area__right {
margin-left: 16px;
}
}

View File

@@ -1,74 +1,75 @@
<template>
<section class="buildingStatistics">
<ai-title v-if="!isFormDv" title="楼栋统计" isShowBack isShowBottomBorder @onBackClick="$router.push({query:{}}),$parent.info={},$parent.isShowInfo=false,$parent.house=null,$parent.chooseBuildId='',$parent.showStatistics=false, $parent.type='0'"/>
<ai-title v-if="!isFormDv" title="楼栋统计" isShowBack isShowBottomBorder
@onBackClick="$router.push({query:{}}),$parent.info={},$parent.isShowInfo=false,$parent.house=null,$parent.chooseBuildId='',$parent.showStatistics=false, $parent.type='0'"/>
<div class="buildingPane">
<div class="bgItem tree"/>
<div class="building">
<template v-if="floorRooms.length>0">
<div class="buildingSignboard">{{ `${currentBuilding.buildingNumber}${unitNumber}单元` }}
</div>
<el-scrollbar class="floors">
<div class="floor" v-for="(fl,j) in floorRooms" :key="j">
<div class="room" v-for="(op,i) in fl" :key="op.id" @click="handleSelectRoom(op,$event)" @touchstart="handleSelectRoom(op,$event)" :class="[{none:op.livingNumber==0,selected:selected.houseCode==op.houseCode},handleTipsHighlight(op.tips)]">
{{ op.houseCode }}
<div v-if="op.livingNumber==0">无人</div>
<div v-show="op.id==selected.id" class="detail" @click.stop :style="{left:position.x,top:position.y}">
<el-row class="popupHeader" type="flex" justify="space-between" align="middle">
<span>{{selected.houseCode}}详情</span>
<ai-icon icon="iconClean" @click.native.stop="selected={}"/>
</el-row>
<div class="family-member">
<h2>房主信息</h2>
<div v-for="(item,index) in selected.owner" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{item.name}}</label>
</div>
<span style="color: #2266FF">{{root.dict.getLabel("houseLivingType",item.livingType)}}</span>
</div>
<div class="family-member__item">
<div class="member-left">
<label>联系方式</label>
</div>
<span style="color: #2266FF;">{{item.phone}}</span>
<div class="building">
<template v-if="floorRooms.length>0">
<div class="buildingSignboard" v-text="`${currentBuilding.buildingNumber}栋 ${unitNumber}单元`"/>
<el-scrollbar class="floors">
<div class="floor" v-for="(fl,j) in floorRooms" :key="j">
<div class="room" v-for="op in fl" :key="op.id" @click="handleSelectRoom(op,$event)" @touchstart="handleSelectRoom(op,$event)"
:class="[{none:op.livingNumber==0,selected:selected.houseCode==op.houseCode},handleTipsHighlight(op.tips)]">
{{ op.houseCode }}
<div v-if="op.livingNumber==0">无人</div>
<div v-show="op.id==selected.id" class="detail" @click.stop :style="{left:position.x,top:position.y}">
<el-row class="popupHeader" type="flex" justify="space-between" align="middle">
<span>{{ selected.houseCode }}详情</span>
<ai-icon icon="iconClean" @click.native.stop="selected={}"/>
</el-row>
<div class="family-member">
<h2>房主信息</h2>
<div v-for="(item,index) in selected.owner" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{ item.name }}</label>
</div>
<span style="color: #2266FF">{{ root.dict.getLabel("houseLivingType", item.livingType) }}</span>
</div>
<h2>承租人信息</h2>
<div v-for="(item,index) in selected.renter" :key="item.id">
<div class="family-member__item" >
<div class="member-left">
<label>{{item.name}}</label>
</div>
<span style="color: #2266FF">{{root.dict.getLabel("houseLivingType",item.livingType)}}</span>
</div>
<div class="family-member__item">
<div class="member-left">
<label>联系方式</label>
</div>
<span>{{item.phone}}</span>
<div class="family-member__item">
<div class="member-left">
<label>联系方式</label>
</div>
<span style="color: #2266FF;">{{ item.phone }}</span>
</div>
</div>
<h2>实际居住人员</h2>
<div v-for="(item,index) in selected.live" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{item.name}}</label>
</div>
<span>{{root.dict.getLabel("householdRelation",item.relation)}}</span>
<h2>承租人信息</h2>
<div v-for="(item,index) in selected.renter" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{ item.name }}</label>
</div>
<span style="color: #2266FF">{{ root.dict.getLabel("houseLivingType", item.livingType) }}</span>
</div>
<div class="family-member__item">
<div class="member-left">
<label>联系方式</label>
</div>
<span>{{ item.phone }}</span>
</div>
</div>
<h2>实际居住人员</h2>
<div v-for="(item,index) in selected.live" :key="item.id">
<div class="family-member__item">
<div class="member-left">
<label>{{ item.name }}</label>
</div>
<span>{{ root.dict.getLabel("householdRelation", item.relation) }}</span>
</div>
</div>
</div>
</div>
</div>
</el-scrollbar>
</template>
<ai-empty v-else>请在<b>小区总览</b>中选取楼栋单元</ai-empty>
<div class="bottom"/>
</div>
<building-tool-bar></building-tool-bar>
</div>
</el-scrollbar>
</template>
<ai-empty v-else>请在<b>小区总览</b>中选取楼栋单元</ai-empty>
<div class="bottom"/>
</div>
<building-tool-bar/>
</div>
</section>
</template>
@@ -96,11 +97,11 @@ export default {
rooms: [],
selected: {},
currentBuilding: {},
unitNumber:1,
unitNumber: 1,
tips: [],
position:{
x:"",
y:""
position: {
x: "",
y: ""
},
}
},
@@ -115,23 +116,23 @@ export default {
}
},
created() {
this.dict.load('householdRelation', 'residentTipType',"houseLivingType")
this.dict.load('householdRelation', 'residentTipType', "houseLivingType")
if (this.isFormDv && this.query.buildingId) {
this.getRoomsByBuilding(this.query.buildingId, this.query.unitNum)
this.currentBuilding = { buildingNumber: this.query.buildingNumber}
this.currentBuilding = {buildingNumber: this.query.buildingNumber}
this.unitNumber = this.query.unitNum
return false
}
this.getRoomsByBuilding(this.$route.query?.buildingId,this.$route.query?.unitNum)
this.getRoomsByBuilding(this.$route.query?.buildingId, this.$route.query?.unitNum)
this.currentBuilding = {buildingNumber: this.$route.query?.buildingNumber};
this.unitNumber = this.$route.query?.unitNum;
},
methods: {
handleSelectRoom(room, e) {
console.log(e)
if (room.livingNumber>0) {
this.$nextTick(()=>{
if (room.livingNumber > 0) {
this.$nextTick(() => {
this.position.x = e.pageX + 40 + "px"
this.position.y = e.pageY + "px"
this.selected = room;
@@ -140,15 +141,17 @@ export default {
// this.getRoomDetail(room.id)
}
},
selectedBuilding(building,unitNumber) {
selectedBuilding(building, unitNumber) {
this.selected = {}
this.tips = []
this.$router.push({query: {...this.$route.query, buildingId: building.id,unitNum:unitNumber}}).catch(e=>{e})
this.$router.push({query: {...this.$route.query, buildingId: building.id, unitNum: unitNumber}}).catch(e => {
e
})
this.currentBuilding = building
this.unitNumber = unitNumber
this.getRoomsByBuilding(building.id,unitNumber)
this.getRoomsByBuilding(building.id, unitNumber)
},
getRoomsByBuilding(buildingId,unitNumber) {
getRoomsByBuilding(buildingId, unitNumber) {
this.root.instance.post("/app/appcommunityhouseinfo/list", null, {
params: {
unitNumber,
@@ -170,11 +173,11 @@ export default {
this.selected = {
...this.selected, ...res.data,
residents: residents.map(e => {
let {tips} = e
//显示为户主
let relationLabel = e.householdName == 1 ? "户主" : this.root.dict.getLabel("householdRelation", e.householdRelation)
return {...e, tips: tips ? tips.split("|") : [], relationLabel}
}
let {tips} = e
//显示为户主
let relationLabel = e.householdName == 1 ? "户主" : this.root.dict.getLabel("householdRelation", e.householdRelation)
return {...e, tips: tips ? tips.split("|") : [], relationLabel}
}
)
}
}
@@ -197,7 +200,7 @@ export default {
display: flex;
flex-direction: column;
::v-deep .ailist-title{
::v-deep .ailist-title {
margin: 0 20px;
}
@@ -337,29 +340,37 @@ export default {
::v-deep .floors {
max-height: 520px;
max-width: 60vw;
margin: 0 20px;
padding: 0 50px;
position: relative;
.el-scrollbar__wrap {
overflow-x: hidden;
margin-bottom: 0 !important;
&:before {
display: block;
content: " ";
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-image: url("https://cdn.cunwuyun.cn/buildSta/floor.png");
background-size: 100% 105px;
}
}
.floor {
margin: 0 20px;
position: relative;
height: 105px;
flex-shrink: 0;
max-width: calc(100% - 40px);
display: flex;
flex-shrink: 0;
align-items: center;
background-image: url("https://cdn.cunwuyun.cn/buildSta/floor.png");
background-size: 100% 105px;
padding: 0 30px;
box-sizing: border-box;
gap: 20px;
.room {
width: 60px;
height: 72px;
flex-shrink: 0;
background-image: url("https://cdn.cunwuyun.cn/buildSta/room.png");
text-align: center;
padding-top: 20px;

View File

@@ -5,8 +5,8 @@
<div class="building" v-for="(value,name) in buildingUnits" :key="name">
<div class="unit" v-for="(op,j) in value" :key="j" @click="sta.selectedBuilding(op,j+1)"
:class="{selected:sta.unitNumber==j+1 && sta.currentBuilding.buildingNumber==name}">
<b>{{ name}}</b>
<div>{{ j+1 }}单元</div>
<b>{{ name }}</b>
<div>{{ j + 1 }}单元</div>
</div>
</div>
</div>
@@ -22,7 +22,7 @@ export default {
buildingUnits() {
let obj = {}
this.units.map(e => {
for(let i=0;i<e.unitNumber;i++){
for (let i = 0; i < e.unitNumber; i++) {
obj[e.buildingNumber]?.push(e) || (obj[e.buildingNumber] = [e])
}
})
@@ -57,6 +57,8 @@ export default {
<style lang="scss" scoped>
.communityOverview {
max-width: 400px;
max-height: 600px;
overflow-y: auto!important;
.units {
display: flex;
@@ -68,7 +70,7 @@ export default {
display: flex;
align-items: center;
height: auto;
flex-wrap: wrap;
flex-wrap: wrap;
.unit {
margin-right: 10px;

View File

@@ -0,0 +1,163 @@
<template>
<section class="AiUserPicker">
<div v-if="$slots.default " @click="handleSelect">
<slot/>
</div>
<div class="AiWechatSelecter-userlist" v-else>
<div class="user-item" v-for="(item, index) in value" :key="index">
<img :src="getAvatar(item)">
<div class="itemLabel" v-text="item.name"/>
<i class="iconfont iconwarning" @click="removeUser(index)"/>
</div>
<div class="user-add" @click="handleSelect">
<div class="userlist-add__icon">
<i class="el-icon-plus"/>
</div>
<span>选择</span>
</div>
</div>
<ai-dialog title="选择人员" :visible.sync="dialog" width="1100px" @onConfirm="submit" @close="selected=[]">
<ai-table-select :instance="instance" v-model="selected" multiple action="/app/wxcp/wxuser/list?status=1" valueObj extra="mobile"/>
</ai-dialog>
</section>
</template>
<script>
export default {
name: "AiUserPicker",
model: {
prop: 'value',
event: 'change',
},
props: {
value: {default: () => []},
instance: Function,
multiple: {default: true},
props: {
default: () => ({
label: 'name',
id: 'id'
})
},
},
data() {
return {
dialog: false,
selected: [],
}
},
methods: {
removeUser(i) {
let list = this.$copy(this.value)
list.splice(i, 1)
this.$emit("change", list)
},
submit() {
this.$emit("change", this.selected)
this.dialog = false
},
handleSelect() {
this.selected = this.$copy(this.value)
this.dialog = true
},
getAvatar(row){
return row.avatar||row.photo||'https://cdn.cunwuyun.cn/dvcp/h5/defaultAvatar.png'
}
}
}
</script>
<style lang="scss" scoped>
.AiUserPicker {
.AiWechatSelecter-userlist {
display: flex;
align-items: center;
flex-wrap: wrap;
.user-add {
margin-bottom: 6px;
.userlist-add__icon {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
margin-bottom: 4px;
border-radius: 2px;
border: 1px solid #CCCCCC;
cursor: pointer;
&:hover {
opacity: 0.6;
}
i {
color: #CCCCCC;
font-size: 20px;
}
}
span {
display: block;
width: 100%;
line-height: 22px;
text-align: center;
color: #888888;
font-size: 14px;
}
}
.user-item {
position: relative;
margin-bottom: 6px;
margin-right: 16px;
width: 40px;
text-align: center;
display: flex;
align-items: center;
flex-direction: column;
img {
display: block;
width: 40px;
height: 40px;
margin-bottom: 4px;
border-radius: 2px;
border: 1px solid #CCCCCC;
}
i {
position: absolute;
top: 0;
right: 0;
padding: 2px;
font-size: 16px;
background: #fff;
border-radius: 50%;
cursor: pointer;
transform: translate(40%, -100%);
height: 16px;
&:hover {
opacity: 0.6;
}
}
.itemLabel {
display: block;
width: 60px;
line-height: 22px;
text-align: center;
color: #888888;
font-size: 14px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
}
}
}
</style>

View File

@@ -5,6 +5,7 @@
* @param params showList:打印加载的应用;apps:加载的应用文件名数组
*/
import core from './core.import'
import dvui from '../project/dvui/entries'
const install = function (Vue, params) {
if (install.installed) return
@@ -25,7 +26,7 @@ const install = function (Vue, params) {
apps.push(app.component)
Vue.component(app.name, app.component)
})
!!params?.showList && console.log(apps.map(e => e.name))
Vue.use(dvui)
return Promise.resolve(apps)
}

View File

@@ -33,9 +33,11 @@
:maxLength="15"
placeholder="请输入姓名"
v-model="form.name"
>
<template slot="append" v-if="!isEdit">
<ai-person-select
:url="'/app/appresident/list?areaId='+user.info.areaId"
:instance="instance"
@selectPerson="checkName"
>
@@ -253,7 +255,7 @@
placeholder="请选择入党时间"
style="width: 100%"
format="yyyy-MM-dd"
:value-format="'yyyy-MM-dd' + ' 00:00:00'"
:value-format="'yyyy-MM-dd'"
>
</el-date-picker>
</el-form-item>
@@ -762,6 +764,7 @@
</template>
<script>
import {mapState} from "vuex";
export default {
name: "Add",
@@ -771,6 +774,7 @@ export default {
selected: Object
},
computed: {
...mapState(["user"]),
isEdit() {
return !!this.$route.query.id;
},

View File

@@ -295,5 +295,9 @@ export default {
width: 100%;
}
}
::v-deep .is-current>.el-tree-node__content{
width: 100%!important;
padding-right: 16px!important;
}
}
</style>

View File

@@ -10,7 +10,7 @@
</el-button>
</template>
<template #right>
<el-input size="small" placeholder="搜索党员/四邻信息" v-model="search.name" clearable
<el-input size="small" placeholder="搜索户主姓名" v-model="search.residentName" clearable
@change="page.current=1,getTableData()" suffix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
@@ -36,7 +36,7 @@
<el-table-column slot="resident">
<template #header>
<b v-text="`户主信息列表`"/>
<el-input class="fill" v-model="list.con" size="small" placeholder="搜索姓名/身份证号" clearable
<el-input class="fill searchbar" v-model="list.con" size="small" placeholder="搜索姓名/身份证号" clearable
@change="list.current=1,getResident()"/>
</template>
<template slot-scope="{row}">
@@ -92,7 +92,7 @@ export default {
},
data() {
return {
search: {name: "", ids: ""},
search: {residentName: "", ids: ""},
page: {current: 1, size: 10, total: 0},
tableData: [],
dialog: false,
@@ -220,5 +220,9 @@ export default {
}
}
}
::v-deep.searchbar {
padding-right: 0;
}
}
</style>

View File

@@ -2,7 +2,7 @@
<section class="residentDetail">
<ai-detail>
<ai-title slot="title" :title="pageTitle" isShowBack @onBackClick="back" isShowBottomBorder>
<template v-if="showDetail" #rightBtn>
<template v-if="isEdit" #rightBtn>
<el-button @click="beforeWriteOff()" icon="el-icon-switch-button" v-if="baseInfo.fileStatus==0">注销档案
</el-button>
<el-button icon="iconfont iconDelete" @click="handleDelete()" v-if="permissions('app_appresident_del')">
@@ -13,7 +13,7 @@
<template #content>
<el-form class="content-right" :model="baseInfo" ref="ruleForm" :rules="rules" label-width="130px"
label-position="right" size="small">
<el-tabs tab-position="left" v-if="showDetail" v-model="currentTab">
<el-tabs tab-position="left" v-if="isEdit" v-model="currentTab">
<el-tab-pane label="基本信息">
<ai-edit-card :title="baseInfo.name||'基本信息'" :show-btn="permissions('app_appresident_edit')"
@save="saveFrom" @cancel="getDetail(baseInfo.id)">
@@ -24,17 +24,17 @@
<el-input
v-model="baseInfo.name"
autocomplete="off"
size="small"
placeholder="请输入姓名"
maxlength="20"
:disabled="isEdit"
show-word-limit/>
</el-form-item>
<el-form-item label="身份证号:" prop="idNumber">
<el-input v-model="baseInfo.idNumber" placeholder="请输入身份证号" :maxlength="18" show-word-limit
@change="idChange"/>
@change="idChange" :disabled="isEdit"/>
</el-form-item>
<el-form-item label="性别:" prop="sex">
<ai-select v-model="baseInfo.sex" :selectList="dict.getDict('sex')"/>
<ai-select v-model="baseInfo.sex" :selectList="dict.getDict('sex')" :disabled="isEdit"/>
</el-form-item>
</div>
<el-form-item label="个人照片:" prop="photo" class="fill">
@@ -200,7 +200,7 @@
</ai-table>
</div>
</ai-card>
<tags-manage v-if="currentTab=='0'&&baseInfo.id" v-bind="$props" :resident-id="baseInfo.id"/>
<tags-manage v-if="currentTab=='0'&&baseInfo.id&&permissions('app_appresidentlabelinfo_detail')" v-bind="$props" :resident-id="baseInfo.id"/>
</el-tab-pane>
<el-tab-pane label="资产信息" lazy>
<personal-assets v-if="currentTab==1&&baseInfo.id" :resident-id="baseInfo.id" v-bind="$props"/>
@@ -357,7 +357,7 @@
</template>
</el-form>
</template>
<template v-if="!showDetail" #footer>
<template v-if="!isEdit" #footer>
<el-button @click="back">取消</el-button>
<el-button type="primary" @click="saveFrom()">保存</el-button>
</template>
@@ -378,7 +378,7 @@
<ai-info-item label="政治面貌" :value="dict.getLabel('politicsStatus', familyInfo.politicsStatus)"/>
<ai-info-item label="兵役状况" :value="dict.getLabel('militaryStatus', familyInfo.militaryStatus)"/>
<ai-info-item label="宗教信仰" :value="dict.getLabel('faithType', familyInfo.faithType)"/>
<ai-info-item label="职业" :value="dict.getLabel('faithType', familyInfo.job)"/>
<ai-info-item label="职业" :value="dict.getLabel('job', familyInfo.job)"/>
<ai-info-item label="现住址" isLine :value="[familyInfo.currentAreaName, familyInfo.currentAddress].join('')"/>
</ai-wrapper>
<ai-avatar v-model="familyInfo.imgUrl" :editable="false"/>
@@ -546,12 +546,12 @@ export default {
},
computed: {
...mapState(["user"]),
showDetail() {
isEdit() {
return !!this.$route.query?.id
},
pageTitle() {
let {name} = this
return this.showDetail ? `${name}信息` : `添加${name}`
return this.isEdit ? `${name}信息` : `添加${name}`
},
hasSpecial() {
//是否有特殊人员信息
@@ -561,7 +561,7 @@ export default {
return [
{
label: "与户主关系", align: 'center',
render: (h, {row}) => h('p', this.dict.getLabel('householdRelation', row.householdRelation || "户主"))
render: (h, {row}) => h('p', this.dict.getLabel('householdRelation', row.householdRelation))
},
{label: "姓名", prop: "name"},
{label: "性别", prop: "sex", dict: "sex", align: 'center'},
@@ -651,6 +651,8 @@ export default {
},
showFamily(row) {
this.familyInfo = row;
let {birthday} = this.idCardNoUtil.getIdCardInfo(this.familyInfo.idNumber)
this.familyInfo.birthday = birthday
if (this.familyInfo.photo) {
this.familyInfo.imgUrl = this.familyInfo.photo.split(";")[0];
} else {
@@ -691,7 +693,7 @@ export default {
},
created() {
this.disabledLevel = this.user.info.areaMap[this.user.info.areaId].length;
if (!this.showDetail) {
if (!this.isEdit) {
// this.baseInfo.householdAreaId = JSON.parse(JSON.stringify(this.user.info.areaId))
this.baseInfo.currentAreaId = JSON.parse(JSON.stringify(this.user.info.areaId))
this.$nextTick(() => this.$refs.ruleForm?.resetFields())

View File

@@ -599,5 +599,9 @@ export default {
}
}
}
::v-deep .is-current>.el-tree-node__content{
width: 100%!important;
padding-right: 16px!important;
}
}
</style>

View File

@@ -3,6 +3,15 @@
<ai-list>
<ai-title slot="title" title="党员积分" isShowBottomBorder/>
<template #content>
<ai-search-bar>
<template #right>
<ai-import :instance="instance" name="党员积分" title="导入党员积分"
suffixName="xlsx"
url="/app/apppartyintegralinfo/downloadTemplate"
importUrl="/app/apppartyintegralinfo/import"
@onSuccess="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">

View File

@@ -1,73 +1,72 @@
<template>
<div class="doc-circulation ailist-wrapper">
<keep-alive :include="['List']">
<component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component>
<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'
import Detail from './components/Detail'
import List from './components/List'
import Add from './components/Add'
import Detail from './components/Detail'
export default {
name: 'AppContentManage',
label: '内容管理',
export default {
name: 'AppContentManage',
label: '内容管理',
props: {
instance: Function,
dict: Object
},
props: {
instance: Function,
dict: Object
},
data () {
return {
component: 'List',
params: {},
include: []
data() {
return {
component: 'List',
params: {},
include: []
}
},
components: {
Add,
List,
Detail
},
created() {
this.dict.load("yesOrNo")
},
methods: {
onChange(data) {
if (data.type === 'Add') {
this.component = 'Add'
this.params = data.params
}
},
components: {
Add,
List,
Detail
},
if (data.type === 'Detail') {
this.component = 'Detail'
this.params = data.params
}
mounted () {
},
if (data.type === 'list') {
this.component = 'List'
this.params = data.params
methods: {
onChange (data) {
if (data.type === 'Add') {
this.component = 'Add'
this.params = data.params
}
if (data.type === 'Detail') {
this.component = 'Detail'
this.params = data.params
}
if (data.type === 'list') {
this.component = 'List'
this.params = data.params
this.$nextTick(() => {
if (data.isRefresh) {
this.$refs.component.getList()
}
})
}
this.$nextTick(() => {
if (data.isRefresh) {
this.$refs.component.getList()
}
})
}
}
}
}
</script>
<style lang="scss">
.doc-circulation {
height: 100%;
background: #F3F6F9;
overflow: auto;
}
.doc-circulation {
height: 100%;
background: #F3F6F9;
overflow: auto;
}
</style>

View File

@@ -9,7 +9,8 @@
<template #content>
<el-form class="ai-form" :model="form" label-width="120px" ref="form">
<el-form-item label="模块名称" style="width: 100%;" prop="moduleName" :rules="[{required: true, message: '请输入模块名称', trigger: 'blur'}]">
<el-input type="input" style="width: 300px" size="small" v-model="form.moduleName" clearable placeholder="请输入模块名称" maxlength="30" show-word-limit></el-input>
<el-input type="input" style="width: 300px" size="small" v-model="form.moduleName" clearable placeholder="请输入模块名称" maxlength="30"
show-word-limit></el-input>
</el-form-item>
<el-form-item prop="menuName" label="菜单名称" :rules="[{required: true, message: '请选择菜单', trigger: 'change'}]">
<el-input type="input" style="width: 300px" disabled size="small" v-model="form.menuName" clearable placeholder="请选择菜单">
@@ -24,25 +25,30 @@
<el-radio label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="是否可评论" style="width: 100%;" prop="isComment" :rules="[{required: true, message: '请选择是否可评论'}]">
<el-radio-group v-model="form.isComment">
<el-radio v-for="op in dict.getDict('yesOrNo')" :key="op.dictValue" :label="op.dictValue">{{ op.dictName }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</template>
</ai-card>
<ai-dialog
:visible.sync="isShowAdd"
width="880px"
height="580px"
title="选择菜单"
@close="onClose"
@onConfirm="onConfirm">
:visible.sync="isShowAdd"
width="880px"
height="580px"
title="选择菜单"
@close="onClose"
@onConfirm="onConfirm">
<el-tree
:data="treeData"
node-key="id"
ref="tree"
@node-click="onChange"
highlight-current
:default-expanded-keys="defaultExpandedKeys"
:default-checked-keys="defaulCheckedKeys"
:props="defaultProps">
:data="treeData"
node-key="id"
ref="tree"
@node-click="onChange"
highlight-current
:default-expanded-keys="defaultExpandedKeys"
:default-checked-keys="defaulCheckedKeys"
:props="defaultProps">
</el-tree>
</ai-dialog>
</template>
@@ -54,130 +60,130 @@
</template>
<script>
import { mapState } from 'vuex'
import {mapState} from 'vuex'
export default {
name: 'Add',
export default {
name: 'Add',
props: {
instance: Function,
dict: Object,
params: Object
},
props: {
instance: Function,
dict: Object,
params: Object
},
data () {
return {
info: {},
form: {
moduleName: '',
menuId: '',
menuName: '',
needExamine: '0'
},
isShowAdd: false,
treeData: [],
id: '',
chooseNode: {},
defaultExpandedKeys: [],
defaulCheckedKeys: [],
defaultProps: {
children: 'subSet',
label: 'name',
disabled: e => {
return e.type !== '1'
}
data() {
return {
info: {},
form: {
moduleName: '',
menuId: '',
menuName: '',
needExamine: '0'
},
isShowAdd: false,
treeData: [],
id: '',
chooseNode: {},
defaultExpandedKeys: [],
defaulCheckedKeys: [],
defaultProps: {
children: 'subSet',
label: 'name',
disabled: e => {
return e.type !== '1'
}
}
},
computed: {
...mapState(['user'])
},
created () {
this.getMenuList()
if (this.params && this.params.id) {
this.id = this.params.id
this.getInfo(this.params.id)
}
},
methods: {
getInfo (id) {
this.instance.post(`/app/appcontentmoduleinfo/queryDetailById?id=${id}`).then(res => {
if (res.code === 0) {
this.form = res.data
}
})
},
showAdd () {
this.isShowAdd = true
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.form.menuId)
this.defaultExpandedKeys = [this.form.menuId]
this.chooseNode = {
menuId: this.form.menuId,
menuName: this.form.menuName,
type: '1'
}
})
},
onClose () {
},
onConfirm () {
if (this.chooseNode.type === '1') {
this.form.menuId = this.chooseNode.id
this.form.menuName = this.chooseNode.name
this.isShowAdd = false
} else {
this.$message.error('无法选择')
}
},
onChange (e) {
this.chooseNode = e
},
getMenuList () {
this.instance.post(`/admin/menu/menuTree?containPermission=0`).then(res => {
if (res.code === 0) {
this.treeData = res.data
}
})
},
confirm () {
this.$refs.form.validate((valid) => {
if (valid) {
this.instance.post(`/app/appcontentmoduleinfo/addOrUpdate`, {
...this.form,
id: this.params.id || ''
}).then(res => {
if (res.code == 0) {
this.$message.success('提交成功')
setTimeout(() => {
this.cancel(true)
}, 600)
}
})
}
})
},
cancel (isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh
})
}
}
},
computed: {
...mapState(['user'])
},
created() {
this.getMenuList()
if (this.params && this.params.id) {
this.id = this.params.id
this.getInfo(this.params.id)
}
},
methods: {
getInfo(id) {
this.instance.post(`/app/appcontentmoduleinfo/queryDetailById?id=${id}`).then(res => {
if (res.code === 0) {
this.form = res.data
}
})
},
showAdd() {
this.isShowAdd = true
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.form.menuId)
this.defaultExpandedKeys = [this.form.menuId]
this.chooseNode = {
menuId: this.form.menuId,
menuName: this.form.menuName,
type: '1'
}
})
},
onClose() {
},
onConfirm() {
if (this.chooseNode.type === '1') {
this.form.menuId = this.chooseNode.id
this.form.menuName = this.chooseNode.name
this.isShowAdd = false
} else {
this.$message.error('无法选择')
}
},
onChange(e) {
this.chooseNode = e
},
getMenuList() {
this.instance.post(`/admin/menu/menuTree?containPermission=0`).then(res => {
if (res.code === 0) {
this.treeData = res.data
}
})
},
confirm() {
this.$refs.form.validate((valid) => {
if (valid) {
this.instance.post(`/app/appcontentmoduleinfo/addOrUpdate`, {
...this.form,
id: this.params.id || ''
}).then(res => {
if (res.code == 0) {
this.$message.success('提交成功')
setTimeout(() => {
this.cancel(true)
}, 600)
}
})
}
})
},
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh
})
}
}
}
</script>
<style scoped lang="scss">

View File

@@ -0,0 +1,73 @@
<template>
<section class="AiEditInput" :class="{[align]:true,error}">
<el-input v-if="edit" size="small" v-model="content" @change="handleChange" @blur="cancel" clearable autofocus/>
<div class="valueText" v-else v-text="value" @click="edit=true"/>
</section>
</template>
<script>
export default {
name: "AiEditInput",
model: {
prop: "value",
event: "change"
},
props: {
value: {default: ""},
align: {default: ""},
error: Boolean
},
data() {
return {
edit: false,
content: ""
}
},
methods: {
cancel() {
this.edit = false
},
handleChange(v) {
this.$emit('change', v)
this.$emit('update:error', false)
}
},
watch: {
edit(v) {
v && (this.content = this.$copy(this.value))
}
}
}
</script>
<style lang="scss" scoped>
::v-deep.AiEditInput {
&.error {
background: rgba(#f46, .2);
}
input {
text-align: center;
}
.valueText {
width: 100%;
height: 100%;
min-height: 32px;
display: flex;
align-items: center;
justify-content: center;
}
&.left {
input {
text-align: left
}
.valueText {
justify-content: flex-start;
}
}
}
</style>

View File

@@ -6,61 +6,40 @@
<template slot="content">
<ai-search-bar class="search-bar">
<template #left>
<el-button size="small" type="primary" icon="iconfont iconAdd" @click="toAdd('')">添加模块</el-button>
<el-button size="small" type="primary" icon="iconfont iconAdd" @click="toAdd()">添加模块</el-button>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
style="margin-top: 6px;"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList">
:tableData="tableData"
:col-configs="colConfigs"
:total="total" :dict="dict"
style="margin-top: 6px;"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList">
<el-table-column slot="options" width="160px" fixed="right" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="toAdd(row.id)">编辑</el-button>
<el-button type="text" @click="moduleId = row.id, form.moduleId = row.id, getCateList(), isShowAdd = true">分类</el-button>
<el-button type="text" @click="getCateList(row.id),isShowAdd = true">分类</el-button>
<el-button type="text" @click="remove(row.id)">删除</el-button>
</div>
</template>
</el-table-column>
</ai-table>
<ai-dialog
:visible.sync="isShowAdd"
width="880px"
height="580px"
title="文章分类"
@close="onClose"
@onConfirm="onConfirm(false)">
<el-form ref="form" class="ai-form" :model="form" label-width="110px" label-position="right">
<el-form-item label="分类名称" style="width: 500px;" prop="categoryName" :rules="[{ required: true, message: '请输入分类名称', trigger: 'blur' }]">
<div class="catewrapper">
<el-input size="small" style="width: 300px;" placeholder="请输入分类名称" v-model="form.categoryName">
</el-input>
<el-button style="margin-left: 20px;" size="small" type="primary" icon="iconfont iconAdd" v-if="!id" @click="onConfirm(true)">添加</el-button>
</div>
</el-form-item>
</el-form>
<ai-table
v-if="!id"
class="detail-table__table"
:border="true"
tableSize="small"
:total="cateTotal"
:tableData="cateList"
:col-configs="cateColConfigs"
:current.sync="cateSearch.current"
:size.sync="cateSearch.size"
:stripe="false"
@getList="getCateList">
<ai-dialog :visible.sync="isShowAdd" width="880px" height="580px" title="文章分类" @close="onClose" @onConfirm="submitCategory">
<el-button icon="iconfont iconAdd" type="text" @click="cateList.push({error:false,categoryName:null})">添加分类</el-button>
<ai-table v-if="moduleId" :tableData="cateList" :col-configs="cateColConfigs" :isShowPagination="false" @getList="getCateList">
<el-table-column slot="category" label="分类名称" align="center">
<template slot-scope="{row}">
<ai-edit-input v-model="row.categoryName" :error.sync="row.error"/>
</template>
</el-table-column>
<el-table-column slot="options" width="220px" fixed="right" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="id = row.id, form.categoryName = row.categoryName">编辑</el-button>
<el-button type="text" @click="removeCate(row.id)">删除</el-button>
</div>
<template slot-scope="{ row,$index }">
<el-button type="text" @click="handleMove(row,$index,-1)" :disabled="$index==0">上移</el-button>
<el-button type="text" @click="handleMove(row,$index,1)" :disabled="$index==(cateList.length-1)">下移</el-button>
<el-button type="text" @click="removeCate($index)">删除</el-button>
</template>
</el-table-column>
</ai-table>
@@ -70,158 +49,129 @@
</template>
<script>
export default {
name: 'List',
import AiEditInput from "./AiEditInput";
props: {
instance: Function,
dict: Object
},
export default {
name: 'List',
components: {AiEditInput},
props: {
instance: Function,
dict: Object
},
data() {
return {
search: {
current: 1,
size: 10,
title: ''
},
moduleId: '',
cateSearch: {
current: 1,
size: 10
},
total: 10,
cateList: [],
colConfigs: [
{ prop: 'moduleName', label: '模块名称', align: 'left', width: '200px' },
{ prop: 'menuName', label: '关联菜单', align: 'center' },
{ prop: 'categoryStr', label: '文章分类', align: 'center' },
{ prop: 'needExamine', label: '是否审核', align: 'center', formart: v => v === '0' ? '否' : '是' }
],
cateColConfigs: [
{prop: 'categoryName', label: '分类名称', align: 'center'}
],
form: {
categoryName: '',
moduleId: '',
showIndex: 1
},
cateTotal: 0,
isShowAdd: false,
id: '',
tableData: []
}
},
mounted() {
this.getList()
},
methods: {
getList() {
this.instance.post(`/app/appcontentmoduleinfo/list`, null, {
params: {
...this.search
}
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
data() {
return {
search: {
current: 1,
size: 10,
title: ''
},
moduleId: '',
total: 10,
cateList: [],
colConfigs: [
{prop: 'moduleName', label: '模块名称', align: 'left', width: '200px'},
{prop: 'menuName', label: '关联菜单', align: 'center'},
{prop: 'categoryStr', label: '文章分类', align: 'center'},
{prop: 'needExamine', label: '是否审核', align: 'center', dict: 'yesOrNo'},
{prop: 'isComment', label: '是否可以评论', align: 'center', dict: 'yesOrNo'}
],
cateColConfigs: [
{type: 'index', label: "排序", align: 'center'},
{slot: 'category'}
],
isShowAdd: false,
tableData: []
}
},
getCateList () {
this.instance.post(`/app/appcontentmodulecategory/list`, null, {
params: {
...this.cateSearch,
moduleId: this.moduleId
}
}).then(res => {
if (res.code == 0) {
this.cateList = res.data.records
this.cateTotal = res.data.total
}
})
},
mounted() {
this.getList()
},
removeCate(id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appcontentmodulecategory/delete?ids=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
this.getCateList()
}
})
})
},
remove(id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appcontentmoduleinfo/delete?ids=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
})
},
onConfirm (flag) {
if (!flag && !this.id) {
this.isShowAdd = false
return false
methods: {
getList() {
this.instance.post(`/app/appcontentmoduleinfo/list`, null, {
params: {
...this.search
}
this.$refs.form.validate((valid) => {
if (valid) {
this.instance.post(`/app/appcontentmodulecategory/addOrUpdate`, {
...this.form,
id: this.id || ''
}).then(res => {
if (res.code == 0) {
this.$message.success('提交成功')
this.getList()
this.getCateList()
this.form.categoryName = ''
if (this.id) {
this.id = ''
return false
}
}
})
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
},
getCateList(moduleId) {
this.moduleId = moduleId
this.instance.post(`/app/appcontentmodulecategory/list`, null, {
params: {size: 99999, moduleId}
}).then(res => {
if (res?.data) {
this.cateList = res.data.records.map(e => ({...e, error: false}))
}
})
},
removeCate(i) {
this.$confirm('确定删除该数据?').then(() => {
this.cateList.splice(i, 1)
})
},
handleMove(row, i, forward) {
const tmp = this.$copy(row), target = i + forward
this.cateList.splice(i, 1, this.cateList[target])
this.cateList.splice(target, 1, tmp)
},
remove(id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appcontentmoduleinfo/delete?ids=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
},
onClose () {
this.id = ''
this.moduleId = ''
this.form.categoryName = ''
this.form.moduleId = ''
},
toAdd(id) {
this.$emit('change', {
type: 'Add',
params: {
id: id || ''
})
},
submitCategory() {
if (!this.cateList.some((e, i, arr) => {
arr[i].error = !e.categoryName
if (!e.categoryName) {
this.$message.error(`${i + 1}行未填写分类名称!`)
return true
}
})) {
const {cateList: categorys, moduleId} = this
this.instance.post(`/app/appcontentmodulecategory/addOrUpdate2`, {
categorys, moduleId
}).then(res => {
if (res?.code == 0) {
this.$message.success('提交成功')
this.isShowAdd = false
this.getList()
}
})
}
},
onClose() {
this.moduleId = ''
this.cateList = []
},
toAdd(id) {
this.$emit('change', {
type: 'Add',
params: {id}
})
}
}
}
</script>
<style lang="scss" scoped>
.notice {
.catewrapper {
display: flex;
align-items: center;
}
.notice {
.catewrapper {
display: flex;
align-items: center;
}
}
</style>

View File

@@ -118,6 +118,7 @@ export default {
linkName: [{ required: true, message: '请输入联系人', trigger: 'change' }],
linkPhone: [{ required: true, message: '请输入联系方式', trigger: 'change' }],
},
flag: true
}
},
// 计算
@@ -148,8 +149,10 @@ export default {
// 确定新增
confirm() {
if(!this.flag) return
this.$refs['ruleForm'].validate((valid) => {
if (valid) {
this.flag = false
this.instance
.post(`/app/appjob/addOrUpdate`, {
title: this.formData.title,

View File

@@ -95,9 +95,11 @@
})
},
remove(id) {
remove(ids) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appjob/delete?id=${id}`).then(res => {
this.instance.post(`/app/appjob/delete`,null,{
params:{ids}
}).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()

View File

@@ -83,7 +83,7 @@
{ prop: 'phone', label: '网格员联系方式', align: 'center' },
{ prop: 'povertyNumber', label: '监测家庭数量', align: 'center' },
{ prop: 'logNumber', label: '开展走访次数', align: 'center' },
{ prop: 'povertyHouseholdNumber', label: '已走访家庭数量', align: 'center' },
// { prop: 'povertyHouseholdNumber', label: '已走访家庭数量', align: 'center' },
{ prop: 'finishRate', label: '走访进度', align: 'center', formart: v => (v * 100).toFixed(1) + '%' }
]
}

View File

@@ -21,6 +21,14 @@
<span>解除风险户数</span>
<h2 style="color: red">{{ totalInfo['解除风险户数'] }}</h2>
</div>
<div class="statistics-top__item">
<span>脱贫户户数</span>
<h2 style="color: pink">{{ totalInfo['脱贫户户数'] }}</h2>
</div>
<div class="statistics-top__item">
<span>脱贫户人口总数</span>
<h2>{{ totalInfo['脱贫人口总数'] }}</h2>
</div>
</div>
<div class="info">
<ai-card title="饮用水和三保障情况">
@@ -41,14 +49,17 @@
</template>
<template #content>
<div class="progress-wrapper">
<div class="progress">
<!-- -->
<div class="progress" v-if="logList.length">
<div class="item" v-for="(item, index) in logList" :key="index">
<h2>{{ item.createUserName }}</h2>
<el-progress :percentage="item.finishRate"></el-progress>
</div>
</div>
<AiEmpty v-else></AiEmpty>
</div>
</template>
</ai-card>
</div>
<ai-card title="帮扶走访情况">
@@ -283,6 +294,10 @@
<style lang="scss" scoped>
.AppAssessment {
::v-deep .ai-empty {
margin-bottom: 0;
font-size: 12px;
}
.info {
display: flex;
justify-content: space-between;

View File

@@ -0,0 +1,61 @@
<template>
<div class="AppHelpDeclaration">
<keep-alive :include="['List']">
<component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component>
</keep-alive>
</div>
</template>
<script>
import Detail from './components/Detail'
import List from './components/List'
export default {
name: "AppHelpDeclaration",
label: '帮扶申报',
components: {List, Detail},
props: {
instance: Function,
dict: Object,
permissions: Function
},
data() {
return {
component: 'List',
params: {},
include: []
}
},
created(){
},
methods:{
onChange (data) {
if (data.type === 'detail') {
this.component = 'Detail'
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>
.AppHelpDeclaration{
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,314 @@
<template>
<section class="detail">
<ai-detail>
<template #title>
<ai-title title="帮扶申请详情" isShowBottomBorder isShowBack @onBackClick="cancel(true)">
<template #rightBtn>
<el-button type="primary" @click="changeStatus('转交事件')" size="small" v-if="$permissions('app_apphelpdeclarationinfo_forward') && form.status != 2 && form.status != 3">转交事件</el-button>
<el-button type="primary" @click="changeStatus('审核处理')" size="small" v-if="$permissions('app_apphelpdeclarationinfo_audit') && form.status != 2 && form.status != 3"> 审核处理</el-button>
</template>
</ai-title>
</template>
<template #content>
<div style="display:flex;">
<ai-card title="申请信息" style="flex:2;margin-right:32px;">
<template slot="content">
<ai-wrapper class="mar-t16" label-width="100px" :columnsNumber="2">
<ai-info-item label="申请人姓名:"><span>{{form.name || '-'}}</span></ai-info-item>
<ai-info-item label="身份证号:"><span>{{form.idNumber || '-'}}</span></ai-info-item>
<ai-info-item label="联系方式:"><span>{{form.phone || '-'}}</span></ai-info-item>
<ai-info-item label="申报方式:"><span>{{$dict.getLabel("helpDeclarationType", form.declareType) || '-'}}</span></ai-info-item>
<ai-info-item label="家庭人口数:"><span>{{form.householdNumber || '-'}}</span></ai-info-item>
<ai-info-item label="排查人员:"><span>{{form.createUserName || '-'}}</span></ai-info-item>
<ai-info-item label="申请帮扶原因:"><span>{{form.reason || '-'}}</span></ai-info-item>
<ai-info-item label="上报时间:"><span>{{form.declareTime || '-'}}</span></ai-info-item>
</ai-wrapper>
<ai-wrapper label-width="100px" :columnsNumber="1">
<ai-info-item label="所在地区:"><span>{{form.areaName}}{{form.address || ''}}</span></ai-info-item>
</ai-wrapper>
<ai-wrapper label-width="100px" :columnsNumber="1">
<ai-info-item label="风险说明:"><span>{{form.riskDescription || '-'}}</span></ai-info-item>
</ai-wrapper>
<ai-uploader :instance="instance" disabled v-model="form.files"></ai-uploader>
</template>
</ai-card>
<ai-card title="办理进度" style="flex:1;">
<template #right>
<p style="color:#666;font-size:14px;">当前状态<span :class="'color'+form.status">{{$dict.getLabel("helpDeclarationStatus", form.status) || '-'}}</span></p>
</template>
<template #content>
<div class="ai-steps">
<div class="ai-steps__item" v-for="(item, index) in form.processList" :key="index">
<div class="ai-steps__item--left">
<div class="ai-steps__item--index">{{index+1}}</div>
</div>
<div class="ai-steps__item--right">
<div class="ai-steps__item__avatar">
<img :src="item.avatar" v-if="item.avatar">
<h2 v-else>{{ formatName(item.doUsername) }}</h2>
</div>
<div class="ai-steps__item--content">
<h2>{{item.doUsername}}</h2>
<h2>{{item.description}}</h2>
<p>{{ item.doTime }}</p>
</div>
</div>
</div>
</div>
</template>
</ai-card>
</div>
<ai-dialog :title="dialogTitle" :visible.sync="showDialog" @onConfirm="statusConfirm()" @onCancel="showDialog=false;" @close="$refs.dialogInfo.resetFields()" width="750px">
<div class="addother_main" style="width:100%;">
<el-form :model="dialogInfo" status-icon ref="dialogInfo" label-width="100px" class="demo-ruleForm">
<el-form-item label="转交" prop="name" style="width: 100%;" autocomplete="off" :rules="[{ required: true, message: '请选择转交人员', trigger: 'blur' }]" v-if="dialogTitle == '转交事件'">
<el-input disabled size="small" v-model="dialogInfo.name" placeholder="请选择转交人员">
<template slot="append">
<ai-wechat-selecter :instance="instance" v-model="addUser" :isMultiple="false" @change="onChange" v-if="dialogTitle == '转交事件'">
<el-button size="small">选择</el-button>
</ai-wechat-selecter>
</template>
</el-input>
</el-form-item>
<el-form-item label="处理结果:" required v-else>
<el-radio-group v-model="dialogInfo.auditStatus">
<el-radio label="1">通过审核</el-radio>
<el-radio label="0">驳回申请</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="办理意见:" prop="description" autocomplete="off" :rules="{ required: true, message: '办理意见不能为空', trigger: 'blur' }">
<el-input v-model="dialogInfo.description" autocomplete="off" size="mini" placeholder="请输入..." type="textarea" :rows="4" :maxlength="100" show-word-limit></el-input>
</el-form-item>
<el-form-item label="图片" style="width: 100%;" >
<ai-uploader
:instance="instance"
v-model="dialogInfo.files"
:limit="9">
<template slot="tips">
<p>最多上传9张图片,单个文件最大10MB支持jpgjpegpng格式</p>
</template>
</ai-uploader>
</el-form-item>
</el-form>
</div>
</ai-dialog>
</template>
</ai-detail>
</section>
</template>
<script>
export default {
name: "detail",
props: {
instance: Function,
dict: Object,
permissions: Function,
params: Object
},
data() {
return {
form: {},
showDialog: false,
dialogTitle: '',
dialogInfo: {auditStatus: '1', description: '', files: [], name: ''},
addUser: [],
};
},
computed: {
},
created() {
this.dict.load('helpDeclarationType', 'helpDeclarationStatus', 'helpDeclarationReason');
},
mounted() {
this.form = this.params
this.getDetail()
},
methods: {
formatName (name) {
if(name == undefined){
return
}
return name.substr(name.length - 2, name.length > 2 ? (name.length - 1) : name.length)
},
getDetail() {
this.instance.post(`/app/apphelpdeclarationinfo/queryDetailById?id=${this.params.id}`).then((res) => {
if (res.code == 0) {
this.form = {...res.data}
this.form.files = this.form.files || []
}
});
},
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh
})
},
changeStatus(title) {
this.dialogTitle = title
this.showDialog = true
},
onChange() {
if (!this.addUser.length) {
return this.$message.error('请选择转交人员')
}
this.dialogInfo.name = this.addUser[0].name
this.dialogInfo.wxUserId = this.addUser[0].id
},
statusConfirm() {
this.$refs["dialogInfo"].validate((valid) => {
if (valid) {
var url = '/app/apphelpdeclarationinfo/forward' //转交人员
if(this.dialogTitle == '审核处理') {
url = '/app/apphelpdeclarationinfo/audit'
}
this.dialogInfo.declarationId = this.form.id
this.instance.post(url, {
...this.dialogInfo,
}).then(res => {
if (res.code == 0) {
this.showDialog = false
this.$message.success("操作成功")
this.getDetail()
}
});
}
})
}
},
};
</script>
<style lang="scss" scoped>
.detail {
height: 100%;
overflow: auto;
background: #f3f6f9;
.above{
overflow: hidden;
width: 100%;
.left{
width: 50%;
float: left;
}
.right{
width: 50%;
float: right;
}
.el-select{
width: 100%;
}
.el-date-editor.el-input{
width: 100%;
}
}
.iconEdit,.Edit{
color:#5088FF;
font-size: 12px;
cursor: pointer;
padding-left: 8px;
}
.color0 {
color: #f82;
}
.color1 {
color: #26f;
}
.color2 {
color: #f46;
}
.color3 {
color: #2EA222;
}
}
.ai-steps {
padding-bottom: 40px;
.ai-steps__item {
display: flex;
position: relative;
padding-bottom: 44px;
&:after {
position: absolute;
left: 12px;
top: 26px;
width: 1px;
height: calc(100% - 30px);
background: #DDDDDD;
content: " ";
}
&:last-child {
padding-bottom: 0;
&:after {
display: none;
}
}
.ai-steps__item--left {
position: relative;
margin-right: 16px;
.ai-steps__item--index{
width: 24px;
height: 24px;
line-height: 24px;
border-radius: 50%;
border: 1px solid #ddd;
text-align: center;
color: #ddd;
font-size: 12px;
}
}
.ai-steps__item--right {
flex-shrink: 0;
color: #666;
font-size: 14px;
display: flex;
width: calc(100% - 40px);
.ai-steps__item--content {
span {
color: #333;
font-size: 16px;
}
h2 {
color: #666666;
font-size: 14px;
word-break: break-all;
}
p {
margin-top: 8px;
color: #666666;
font-size: 14px;
}
}
.ai-steps__item__avatar {
width: 40px;
height: 40px;
margin-right: 8px;
img, h2 {
width: 40px;
height: 40px;
line-height: 40px;
text-align: center;
color: #fff;
font-size: 14px;
background: #2266FF;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,240 @@
<template>
<ai-list class="list">
<template slot="title">
<ai-title title="帮扶申报" :instance="instance" isShowBottomBorder isShowArea :disabledLevel="disabledLevel" v-model="areaId" @change="changeArea"></ai-title>
</template>
<template slot="content">
<ai-search-bar>
<template slot="left">
<ai-select
v-model="searchObj.declareReason"
placeholder="申请帮扶原因"
clearable
@change="(page.current = 1), getList()"
:selectList="dict.getDict('helpDeclarationReason')"
></ai-select>
<ai-select
v-model="searchObj.declareType"
placeholder="申报方式"
clearable
@change="(page.current = 1), getList()"
:selectList="dict.getDict('helpDeclarationType')"
></ai-select>
<ai-select
v-model="searchObj.status"
placeholder="状态"
clearable
@change="(page.current = 1), getList()"
:selectList="dict.getDict('helpDeclarationStatus')"
></ai-select>
</template>
<template slot="right">
<el-input placeholder="申请人姓名/联系方式"
v-model="searchObj.name"
size="small"
v-throttle="() => {page.current = 1, getList()}"
clearable
@clear="page.current = 1, searchObj.name = '', getList()"
prefix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="page.total"
ref="aitableex"
:current.sync="page.current"
row-key="id"
default-expand-all
:size.sync="page.size"
@getList="getList"
>
<el-table-column slot="options" label="操作" align="center" width="120">
<template slot-scope="{ row }">
<el-button type="text" @click="goDetail(row)">详情</el-button>
</template>
</el-table-column>
</ai-table>
</template>
</ai-list>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: "list",
props: {
instance: Function,
dict: Object,
permissions: Function,
},
data() {
return {
searchObj: {
declareReason: '',
declareType: null,
status: null,
name: '',
},
page: {
size: 10,
current: 1,
total: 0,
},
tableData: [],
shopList: [],
ids: [],
areaId: '',
disabledLevel: 0,
};
},
computed: {
...mapState(['user']),
colConfigs() {
return [
{
prop: "reason",
label: "申请帮扶原因"
},
{
prop: "riskDescription",
label: "返贫致贫风险说明",
},
{
prop: "areaName",
label: "所在地区",
width: 120,
align: "center",
},
{
prop: "name",
label: "申请人姓名",
width: 120,
align: "center",
},
{
prop: "phone",
label: "联系方式",
width: 120,
align: "center",
},
{
prop: "declareType",
label: "申报方式",
width: 120,
align: "center",
formart: (declareType) =>
this.$dict.getLabel("helpDeclarationType", declareType),
},
{
prop: "declareTime",
label: "申报时间",
width: 120,
align: "center",
},
{
prop: "status",
label: "状态",
width: 120,
align: "center",
render: (h, {row}) => {
return h('span', {style: {color: this.dict.getColor('helpDeclarationStatus', row.status)}}, this.dict.getLabel('helpDeclarationStatus', row.status))
},
},
{slot: "options", label: "操作"},
];
},
},
created() {
this.disabledLevel = this.user.info.areaList.length - 1
this.areaId = this.user.info.areaId
this.dict.load('helpDeclarationType', 'helpDeclarationStatus', 'helpDeclarationReason').then(() => {
this.$nextTick(() => this.getList())
})
},
methods: {
getList() {
this.instance.post(`/app/apphelpdeclarationinfo/list`, null, {
params: {
...this.searchObj,
...this.page,
areaId: this.areaId
},
}).then((res) => {
if (res.code == 0) {
this.tableData = res.data.records;
this.tableData.map((item) => {
if (item.createTime) {
item.createTime = item.createTime.substring(0, 10)
} else {
item.createTime = '-'
}
})
this.page.total = res.data.total;
}
});
},
reset() {
this.page.current = 1
Object.keys(this.searchObj).forEach((e) => {
this.searchObj[e] = "";
});
this.getList();
},
goDetail(row) {
this.$emit('change', {
type: 'detail',
params: {
...row
}
})
},
changeArea() {
this.$nextTick(() => {
this.reset()
})
},
},
};
</script>
<style lang="scss" scoped>
.list {
height: 100%;
overflow: auto;
background: #f3f6f9;
::v-deep .el-range-editor--small.el-input__inner {
width: 258px;
}
::v-deep .dateRange {
.dateLabel {
height: 32px;
border: 1px solid #D0D4DC;
line-height: 32px;
padding: 0 8px;
background: #F5F5F5;
}
.el-input__inner {
border-radius: 0;
transform: translateX(-1px);
}
}
.iconfont {
cursor: pointer;
margin-right: 8px;
}
.iconCorrect {
color: #53b43b;
}
.iconReject {
color: #e75555;
padding: 0 8px;
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More