pyt
2025-03-13 298fbe50e4bc2f477ffa20175a7dd5c41fc0942b
Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/H5/threeSide
12个文件已修改
23个文件已添加
2084 ■■■■■ 已修改文件
H5/components/customPopup.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/main.js 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages.json 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/add-progress/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/certificationAudit/certificationAudit.vue 327 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/certificationAudit/service.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/dispatchWorkOrder/dispatchWorkOrder.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/evaluate/evaluate.vue 459 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/evaluate/service.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/index/index.vue 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/list/list.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/problemReporting/problemReporting.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/progress/progress.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/work-detail/postpone-apply.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/pages/work-detail/work-detail.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/closeImg.png 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/detailImg/bg.png 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/detailImg/img1.png 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/detailImg/img2.png 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/detailImg/img3.png 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/detailImg/img4.png 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/man.png 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/popupBg.png 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/required.png 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/style/_app.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/static/women.png 补丁 | 查看 | 原始文档 | blame | 历史
management/config/routes.ts 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/party/audit/components/index.jsx 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/party/audit/index.jsx 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/party/audit/service.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/party/manage/components/addAndEdit.jsx 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/party/manage/components/export.jsx 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/party/manage/components/index.jsx 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/party/manage/index.jsx 237 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
management/src/pages/party/manage/service.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
H5/components/customPopup.vue
New file
@@ -0,0 +1,106 @@
<template>
    <u-popup :show="show" mode="center" bgColor="transparent" @open="openPopup" :closeOnClickOverlay="false" zIndex="10071">
        <view class="bgImg px-61 pt-46 pb-37 br-28">
            <view class="txt-center font-bold fs-35 color2">
                提示
            </view>
            <slot></slot>
            <view class="fs-27">
                <view v-if="!isOneBtn" class="flex a-center j-between">
                    <view @tap.stop="closeFun" class="h-77 lh-77 shrink0 txt-center px-79 br-48 mr-33 border1">
                        {{closeText}}
                    </view>
                    <view @tap.stop="comfirmFun" class="px-79 py-19 br-48 color1 bgcolor1">{{confirmText}}</view>
                </view>
                <view v-else @tap.stop="comfirmFun" class="lh-70 txt-center w100 br-48 color1 bgcolor1">
                    {{confirmText}}<span v-if="isCountDown && num != 0">({{num}}S)</span>
                </view>
            </view>
        </view>
    </u-popup>
</template>
<script>
    export default {
        props: {
            confirmText: {
                type: String,
                default: '确认'
            },
            closeText: {
                type: String,
                default: '关闭'
            },
            isOneBtn: {
                type: Boolean,
                default: false
            },
            isCountDown: {
                type: Boolean,
                default: false
            }
        },
        data() {
            return {
                timer: null,
                num: 3,
                show: false,
            }
        },
        methods: {
            openPopup() {
                this.timer = setInterval(() => {
                    this.num--
                    if (this.num == 1) {
                        setTimeout(() => {
                            this.num = 0
                            clearInterval(this.timer)
                        }, 900)
                    }
                }, 1000)
            },
            closeFun() {
                this.$emit('close')
            },
            comfirmFun() {
                if (this.isCountDown && this.num != 0) {
                    return
                }
                this.$emit('comfirm')
            },
            showPopup() {
                this.show = true
            },
            closePopup() {
                this.show = false
            },
        }
    }
</script>
<style scoped lang="scss">
    .bgImg {
        width: 516rpx;
        background-image: url('/static/popupBg.png');
        background-size: 100% 212rpx;
        background-repeat: no-repeat;
        background-color: #fff;
    }
    .border1 {
        border: 2rpx solid rgba(0, 0, 0, 0.8);
        box-sizing: border-box;
    }
    .color1 {
        color: #fff;
    }
    .color2 {
        color: rgba(0, 0, 0, 0.8);
    }
    .bgcolor1 {
        background: linear-gradient(270deg, #FC8D55 0%, #FF4948 100%);
    }
</style>
H5/main.js
@@ -1,28 +1,16 @@
import App from './App'
// #ifndef VUE3
import Vue from 'vue'
import store from '@/store/index.js'
import uView from '@/uni_modules/uview-ui'
import './uni.promisify.adaptor'
import CustomPopup from '@/components/customPopup.vue'
Vue.config.productionTip = false
Vue.prototype.$store = store
import uView from '@/uni_modules/uview-ui'
Vue.use(uView)
Vue.component('CustomPopup', CustomPopup)
App.mpType = 'app'
const app = new Vue({
    ...App
})
app.$mount()
// #endif
Vue.use(uView)
// #ifdef VUE3
import {
    createSSRApp
} from 'vue'
export function createApp() {
    const app = createSSRApp(App)
    return {
        app
    }
}
// #endif
app.$mount()
H5/pages.json
@@ -106,6 +106,12 @@
                "navigationBarTitleText" : "党员信息",
                "navigationStyle": "custom"
            }
        },{
            "path": "pages/evaluate/evaluate",
            "style": {
                "navigationBarTitleText": "诉求评价",
                "navigationStyle": "custom"
            }
        },
        {
            "path" : "pages/authentication/authentication",
@@ -114,6 +120,13 @@
                "navigationBarTitleText" : "党员认证",
                "navigationStyle": "custom"
            }
        },{
            "path" : "pages/certificationAudit/certificationAudit",
            "style" :
            {
                "navigationBarTitleText": "党员认证审核",
                "navigationStyle": "custom"
            }
        }
    ],
    "globalStyle": {
H5/pages/add-progress/index.vue
@@ -306,7 +306,7 @@
    }
    .bgcolor1 {
        background: linear-gradient(270deg, rgba(255, 241, 0, 0.5) 0%, rgba(255, 249, 172, 0.25) 48%, rgba(255, 255, 255, 0.2) 100%, #FFFFFF 100%);
        background: linear-gradient( 270deg, rgba(255,241,0,0.5) 0%, rgba(255,249,172,0.25) 48%, rgba(255,255,255,0.2) 100%, #FFFFFF 100%);
    }
    .bgcolor2 {
H5/pages/certificationAudit/certificationAudit.vue
New file
@@ -0,0 +1,327 @@
<template>
    <view>
        <view v-if="list.length == 0 && status == 'noMore'" class="mt-200">
            <image src="../../static/空空如也@2x.png" mode="widthFix" class="w100"></image>
            <view class="txt-center mt-94 fs-27 color9">
                暂无数据
            </view>
        </view>
        <view v-else class="px-31">
            <view class="mt-38 br-19 bgColor3 shadow2 oh pb-31" v-for="(item,index) in list" :key="item.id">
                <view class="pt-21 px-31 flex a-center j-between font-bold">
                    <view class="flex a-center">
                        <view class="fs-31 mr-23">习婕海</view>
                        <view v-if="!index" class="flex a-center pr-19 border3">
                            <image src="@/static/man.png" class="w-38 h-38 shrink0" />
                            <view class="fs-23 ml-12">
                                男
                            </view>
                        </view>
                        <view v-else class="flex a-center pr-19 border4">
                            <image src="@/static/women.png" class="w-38 h-38 shrink0" />
                            <view class="fs-23 ml-12">
                                女
                            </view>
                        </view>
                    </view>
                    <view class="color3 flex a-center fs-31">
                        待审核
                    </view>
                </view>
                <view class="mt-38 mx-31 pt-12 pb-23 px-31 br-19 bgColor8">
                    <view class="flex a-center j-between lh-38 mt-19 fs-27 color11">
                        <view class="font-w400">身份证号</view>
                        <view class="font-bold">500000000000000000</view>
                    </view>
                    <view class="flex a-center j-between lh-38 mt-19 fs-27 color11">
                        <view class="font-w400">联系电话</view>
                        <view class="font-bold">15729765305</view>
                    </view>
                    <view class="flex j-between lh-38 mt-19 fs-27 color11">
                        <view class="font-w400">服务社区</view>
                        <view class="font-bold">仁和区-仁和镇-仁和街社区</view>
                    </view>
                    <view class="flex j-between lh-38 mt-19 fs-27 color11">
                        <view class="font-w400">服务对象</view>
                        <view class="font-bold">文化小区一栋一单元</view>
                    </view>
                    <view class="flex j-between lh-38 mt-19 fs-27 color11">
                        <view class="font-w400">所在党组织</view>
                        <view class="font-bold max-w1">中共攀枝花市委组织部机关中共11攀枝花市委组织部机关</view>
                    </view>
                    <view class="flex wrap mt-19">
                        <image src="/static/logo.png" class="w-142 h-142 mr-12 shrink0 br-19 mb-12" />
                    </view>
                </view>
                <view class="mt-37 border1">
                    <view class="left"></view>
                    <view class="right"></view>
                    <view class="txt-center fs-23 mt-31 color6">
                        申请时间:{{ item.createTime | formatTime }}
                    </view>
                    <view class="flex a-center j-center fs-23 mt-29 txt-center">
                        <view @click.stop="refuse" class="h-58 lh-58 bgColor5 w-192 br-29 color10 border2">
                            拒绝
                        </view>
                        <view @click.stop="pass" class="ml-38 h-58 lh-58 bgColor6 w-192 br-29 color8">
                            通过
                        </view>
                    </view>
                </view>
            </view>
        </view>
        <view class="h-safe-b"></view>
        <CustomPopup ref="tipPoput" @close="closePopup" @comfirm="comfirmPopup">
            <view class="mt-50" :class="suditStatus ? 'mb-38' : 'mb-60'">
                <view class="txt-center fs-31 lh-42 color12">确认审核{{suditStatus ? '拒绝' : '通过'}}所选信息吗?</view>
                <view v-if="suditStatus" class="mt-38">
                    <view class="flex">
                        <image src="/static/required.png" class="w-10 h-10 mt-12 mr-15 shrink0" />
                        <view class="fs-31 lh-42 font-bold">拒绝理由:</view>
                    </view>
                    <view class="border5 br-19 mt-13 px-35 py-27 ">
                        <textarea v-model="reasonsRefusal" placeholder="请输入拒绝理由" class="fs-27 h-178 w100"></textarea>
                        <view v-if="showRequiredTip" class="fs-23 lh-33 color3">拒绝理由必填</view>
                    </view>
                </view>
            </view>
        </CustomPopup>
    </view>
</template>
<script>
    import dayjs from '@/uni_modules/uview-ui/libs/util/dayjs.js'
    import {
        getList
    } from './service.js'
    export default {
        data() {
            return {
                searchParams: {
                    pageNum: 1,
                    pageSize: 10,
                },
                list: [{}, {}],
                status: 'loadMore',
                suditStatus: false,
                reasonsRefusal: '',
                showRequiredTip: false,
            }
        },
        filters: {
            formatTime(val) {
                if (!val) return ''
                return dayjs(val).format('YYYY-MM-DD HH:mm:ss')
            }
        },
        onReachBottom() {
            if (this.status == 'loadMore') {
                this.searchParams.pageNum += 1
                this.fetchList(this.searchParams, (e) => {
                    this.list = [...this.list, ...e.records]
                    if (this.list.length == e.total) {
                        this.status = 'noMore'
                    } else {
                        this.status = 'loadMore'
                    }
                })
            }
        },
        onShow() {
        },
        onReady() {},
        methods: {
            comfirmPopup() {
                if (this.suditStatus) {
                    if (!this.reasonsRefusal) {
                        this.showRequiredTip = true
                        return
                    }
                }
                this.closePopup()
            },
            refuse() {
                this.suditStatus = true
                this.$refs.tipPoput.showPopup()
            },
            pass() {
                this.$refs.tipPoput.showPopup()
            },
            fetchList(params, callback) {
                if (this.status == 'loading') return
                this.status = 'loading'
                getList(params).then(res => {
                    if (res.code == 200) {
                        res.data.records.map(item => {
                            if (item.images) {
                                item.images = item.images.split(',')
                            }
                        })
                        callback(res.data)
                    }
                })
            },
            closePopup() {
                this.$refs.tipPoput.closePopup()
                this.$nextTick(() => {
                    this.suditStatus = false
                    this.showRequiredTip = false
                    this.reasonsRefusal = ''
                })
            },
        }
    }
</script>
<style scoped lang="scss">
    .shadow2 {
        box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
    }
    .color1 {
        color: #4C4C4C;
    }
    .color2 {
        color: #232323;
    }
    .color3 {
        color: #FF4948;
    }
    .color4 {
        color: #929191;
    }
    .color5 {
        color: #000;
    }
    .color6 {
        color: #666666;
    }
    .color7 {
        color: #727272;
    }
    .color8 {
        color: #fff;
    }
    .color9 {
        color: #999999;
    }
    .color10 {
        color: #636363;
    }
    .color11 {
        color: rgba(0, 0, 0, 0.88);
    }
    .color12 {
        color: rgba(0, 0, 0, 0.6);
    }
    .bgColor1 {
        background: linear-gradient(270deg, #FFB318 0%, #FF330D 100%);
        width: 58rpx;
        height: 12rpx;
        border-radius: 6rpx;
        position: absolute;
        left: 0;
        right: 0;
        bottom: -5rpx;
        margin: auto;
    }
    .bgColor2 {
        background-color: #fff;
    }
    .bgColor3 {
        background: linear-gradient(180deg, #FFDCDB 0%, rgba(255, 255, 255, 0) 138rpx, #fff 100%);
    }
    .bgColor4 {
        background: linear-gradient( 270deg, rgba(255,241,0,0.5) 0%, rgba(255,249,172,0.25) 48%, rgba(255,255,255,0.2) 100%, #FFFFFF 100%);
    }
    .bgColor5 {
        background: #F3F3F3;
    }
    .bgColor6 {
        background: linear-gradient(270deg, #FC8D55 0%, #FF4948 100%);
    }
    .bgColor7 {
        background: #FF4948;
    }
    .bgColor8 {
        background: rgba(0, 0, 0, 0.03);
    }
    .border1 {
        border-top: 2rpx solid #EDEEEF;
        position: relative;
        .left {
            width: 40rpx;
            height: 40rpx;
            background-color: #F4F4F4;
            border-radius: 50%;
            position: absolute;
            left: -20rpx;
            top: -20rpx;
        }
        .right {
            width: 40rpx;
            height: 40rpx;
            background-color: #F4F4F4;
            border-radius: 50%;
            position: absolute;
            right: -20rpx;
            top: -20rpx;
        }
    }
    .border2 {
        border: 2rpx solid #E5E5E5;
        box-sizing: border-box;
    }
    .border3 {
        background: #E4EFFF;
        box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
        border-radius: 22rpx;
        border: 2rpx solid #5599FF;
        box-sizing: border-box;
        color: #1677FF;
    }
    .border4 {
        background: #FFEEF1;
        box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
        border-radius: 22rpx;
        border: 2rpx solid #F7636E;
        box-sizing: border-box;
        color: #E5484D;
    }
    .border5 {
        border: 2rpx solid #E9E9E9;
    }
    .max-w1 {
        width: 329rpx;
    }
</style>
H5/pages/certificationAudit/service.js
New file
@@ -0,0 +1,5 @@
import request from '@/utils/request.js'
// 工单列表
export const getList =(params)=>{
    return request.post(`/api/huacheng-sangeshenbian/applet/complaint/list`,params)
}
H5/pages/dispatchWorkOrder/dispatchWorkOrder.vue
@@ -202,7 +202,7 @@
                display: flex;
                justify-content: space-between;
                // height: 106rpx;
                background: linear-gradient(270deg, rgba(255, 241, 0, 0.5) 0%, rgba(255, 249, 172, 0.25) 48%, rgba(255, 255, 255, 0.2) 100%, #FFFFFF 100%);
                background: linear-gradient( 270deg, rgba(255,241,0,0.5) 0%, rgba(255,249,172,0.25) 48%, rgba(255,255,255,0.2) 100%, #FFFFFF 100%);
                box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
                border-radius: 19rpx;
                align-items: center;
H5/pages/evaluate/evaluate.vue
New file
@@ -0,0 +1,459 @@
<template>
    <view class="content">
        <view class="topColor">
        </view>
        <view class="allContent">
            <view class="fs-27 lh-38 font-bold">评价打分</view>
            <view class="mt-25 flex j-between">
                <view class="evaluateItem" v-for="(item,index) in list" :key="index" @click="activeType=item.value"
                    :class="activeType==item.value && 'activeBg'">
                    <image :src="item.img" class="statusImg" />
                    <view class="title">{{item.tit}}</view>
                </view>
            </view>
            <view class="mt-38">
                <view class="fs-27 lh-38 font-bold">评价内容</view>
                <textarea v-model="describe" class="pt-25 pl-31 mt-27 fs-27 br-8 bgcolor4"
                    :class="(rulsFlag && !describe) && 'bgcolor-border'"
                    style="height: 365rpx;width: calc(100% - 31rpx);" placeholder="请输入不超过200字评价" />
                <view v-if="rulsFlag && !describe" class="flex a-center mt-19">
                    <image src="@/static/noNull.png" class="w-35 h-35 mr-13 shrink0" />
                    <view class="fs-23 color99">评价内容不能为空</view>
                </view>
                <view class="fs-27 mt-38 lh-38 font-bold">上传图片</view>
                <view class="flex wrap mt-27">
                    <view class="relative mr-15" v-for="(item, index) in localImageUrls" :key="index">
                        <image v-if="item != 'loading'" :src="item" class="w-140 h-140 shrink0 br-8" />
                        <view v-if="item != 'loading'" class="absolute w-140 h-140 bgcolor5 top0 left0 br-8">
                            <view class="absolute flex a-center j-between px-34"
                                style="top: 50%;left: 50%;transform: translate(-50%,-50%);width: calc(100% - 68rpx);">
                                <image @tap="viewImage(item)" src="@/static/Appeal/amplify.png" class="w-19 h-19" />
                                <image @tap="delImg(item)" src="@/static/Appeal/trash.png" class="w-19 h-19" />
                            </view>
                        </view>
                    </view>
                    <view v-if="imgUrls.includes('loading')"
                        class="w-140 h-140 flex a-center j-center mr-15 border2 br-8">
                        <u-loading-icon></u-loading-icon>
                    </view>
                    <image @tap="uploadImg(1)" src="/static/Appeal/add.png" class="w-140 h-140 shrink0" />
                </view>
                <view class="fs-27 mt-37 lh-38 font-bold">上传视频</view>
                <view class="flex wrap mt-27">
                    <view class="imgOrVedio" v-for="(ite, ind) in video" :key="ind">
                        <video v-if="ite != 'loading'" id="myVideo" class="videoImg shrink0" disabled :controls="false"
                            :show-center-play-btn="false" :src="ite">
                        </video>
                        <view v-if="ite != 'loading'" class="absolute w-140 h-140 bgcolor5 top0 left0 br-8 zIndex999">
                            <view class="absolute flex a-center j-between"
                                style="top: 50%;left: 50%;transform: translate(-50%,-50%);">
                                <image @tap="openVideo(ite)" src="@/static/detailImg/open.png" class="w-140 h-140" />
                            </view>
                            <image @tap="delVideo(ite)" src="@/static/Appeal/trash.png"
                                class="absolute w-19 h-19 zIndex999" style="top: 8rpx;right: 8rpx;" />
                        </view>
                    </view>
                    <view v-if="video.includes('loading')"
                        class="w-140 h-140 flex a-center j-center mr-15 border2 br-8">
                        <u-loading-icon></u-loading-icon>
                    </view>
                    <image @tap="uploadImg(2)" src="@/static/Appeal/add.png" class="w-140 h-140 shrink0" />
                </view>
            </view>
            <view @click.stop="submit" class="mt-38 fs-35 lh-96 br-48 txt-center font-bold bgcolor6 color4 fixed"
                style="width: calc(100% - 62rpx);bottom: calc(env(safe-area-inset-bottom) + 10rpx);">保存</view>
            <view class="btn-box"></view>
            <view class="safe-box"></view>
        </view>
    </view>
</template>
<script>
    import {
        saveProcess,
        getComplaintDetail
    } from './service'
    import config from '@/config/index.js'
    export default {
        data() {
            return {
                complaintId: '', //诉求id
                info: {}, //工单详情
                describe: '', //办理进度描述
                localImageUrls: [], //本地回显的图片
                imgUrls: [], //传给后端的url
                video: [],
                againCklicFlag: true,
                rulsFlag: false,
                activeType: 1,
                list: [{
                    img: '../../static/detailImg/img1.png',
                    tit: '不满意',
                    value: 1
                }, {
                    img: '../../static/detailImg/img2.png',
                    tit: '一般',
                    value: 2
                }, {
                    img: '../../static/detailImg/img3.png',
                    tit: '满意',
                    value: 3
                }, {
                    img: '../../static/detailImg/img4.png',
                    tit: '非常满意',
                    value: 4
                }],
            }
        },
        onLoad(params) {
            // this.complaintId = params.id
            // getComplaintDetail({
            //     id: params.id
            // }).then(res => {
            //     this.info = res.data
            // })
        },
        methods: {
            back() {
                uni.navigateBack({
                    delta: 2
                })
            },
            submit() {
                if (!this.describe) {
                    this.rulsFlag = true
                    return uni.showToast({
                        icon: 'none',
                        title: '请输入办理进度描述'
                    })
                }
                let obj = {
                    complaintId: this.complaintId,
                    describe: this.describe,
                    imgUrl: this.imgUrls.join(','),
                    video: this.video.join(',')
                }
                saveProcess(obj).then(res => {
                    if (res.code == 200) {
                        uni.showToast({
                            title: '提交成功',
                            icon: 'success',
                            mask: true
                        })
                        setTimeout(() => {
                            uni.navigateBack()
                        }, 1500)
                    } else {
                        uni.showToast({
                            title: res.msg,
                            icon: 'none',
                            mask: true
                        })
                    }
                })
            },
            delImg(item) {
                this.localImageUrls = this.localImageUrls.filter(i => i != item)
                this.imgUrls = this.imgUrls.filter(i => i != item)
            },
            delVideo(item) {
                this.video = this.video.filter(i => i != item)
            },
            viewImage(item) {
                uni.previewImage({
                    urls: [item]
                })
            },
            uploadImg(type) {
                // if (!this.againCklicFlag) return
                this.againCklicFlag = false
                if (type == 1) {
                    uni.chooseImage({
                        count: 1,
                        success: (chooseImageRes) => {
                            this.imgUrls.push('loading')
                            this.againCklicFlag = true
                            let imgPathList = chooseImageRes.tempFilePaths;
                            if (imgPathList.length > 0) {
                                uni.uploadFile({
                                    url: config.imageUrl,
                                    filePath: imgPathList[0],
                                    timeout: 1000 * 45,
                                    name: 'file',
                                    header: {
                                        Authorization: uni.getStorageSync('token')
                                    },
                                    success: (res) => {
                                        if (JSON.parse(res.data).code == 200) {
                                            this.imgUrls = this.imgUrls.filter(item => item !=
                                                'loading')
                                            this.$nextTick(() => {
                                                this.imgUrls.push(JSON.parse(res.data)
                                                    .data)
                                                this.localImageUrls.push(imgPathList[0])
                                            })
                                        } else {
                                            this.againCklicFlag = true
                                            this.imgUrls = this.imgUrls.filter(
                                                item => item != 'loading')
                                            uni.showToast({
                                                title: '上传失败,请重新上传',
                                                icon: 'none',
                                                mask: true
                                            })
                                        }
                                    },
                                    fail: (err) => {
                                        this.againCklicFlag = true
                                        this.imgUrls = this.imgUrls.filter(
                                            item => item != 'loading')
                                        uni.showToast({
                                            title: '上传失败,请重新上传',
                                            icon: 'none',
                                            mask: true
                                        })
                                    }
                                })
                            }
                        },
                        fail: () => {
                            this.againCklicFlag = true
                        }
                    })
                } else {
                    uni.chooseVideo({
                        camera: 'back',
                        success: (res) => {
                            this.video.push('loading')
                            this.againCklicFlag = true
                            const tempFilePath = res.tempFilePath;
                            uni.uploadFile({
                                url: config.imageUrl,
                                filePath: tempFilePath,
                                timeout: 1000 * 45,
                                name: 'file',
                                header: {
                                    Authorization: cuni.getStorageSync('token')
                                },
                                success: (res) => {
                                    if (JSON.parse(res.data).code == 200) {
                                        this.video = this.video.filter(item => item !=
                                            'loading')
                                        this.$nextTick(() => {
                                            this.video.push(JSON.parse(res.data).data)
                                        })
                                    } else {
                                        this.againCklicFlag = true
                                        this.video = this.video.filter(
                                            item => item != 'loading')
                                        uni.showToast({
                                            title: '上传失败,请重新上传',
                                            icon: 'none',
                                            mask: true
                                        })
                                    }
                                },
                                fail: (err) => {
                                    this.againCklicFlag = true
                                    this.video = this.video.filter(
                                        item => item != 'loading')
                                    uni.showToast({
                                        title: '上传失败,请重新上传',
                                        icon: 'none',
                                        mask: true
                                    })
                                }
                            })
                        },
                        fail: () => {
                            this.againCklicFlag = true
                        }
                    })
                }
            },
            // 去大屏播放视频
            openVideo(url) {
                uni.navigateTo({
                    url: `/pages/work-detail/maxVideo?url=${url}`
                })
            },
        }
    }
</script>
<style>
    page {
        background: linear-gradient(180deg, #FFFFFF 0%, #F9F9F9 6%, #F8F8F8 100%);
    }
</style>
<style lang="scss" scoped>
    .content {
        width: 100%;
        height: 100%;
    }
    .topColor {
        height: 346rpx;
        background: linear-gradient(180deg, #FFDCDB 0%, rgba(255, 255, 255, 0) 100%);
        // padding: 176rpx 27rpx 17rpx 27rpx;
    }
    .allContent {
        margin-top: -203rpx;
        padding: 38rpx 31rpx 0 31rpx;
        background: #FFFFFF;
        box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
        border-radius: 36rpx 36rpx 0 0;
        height: 100%;
        .evaluateItem {
            flex: 1;
            // height: 175rpx;
            background: rgba(0, 0, 0, 0.03);
            border-radius: 19rpx;
            padding: 25rpx 0 19rpx 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            margin-right: 17rpx;
            .statusImg {
                width: 75rpx;
                height: 75rpx;
            }
            .title {
                font-size: 23rpx;
                color: rgba(0, 0, 0, 0.6);
                line-height: 33rpx;
                margin-top: 23rpx;
            }
        }
        .activeBg {
            background: url('../../static/detailImg/bg.png') no-repeat 100% 100%;
            background-size: 100% 100%;
        }
        .evaluateItem:last-child {
            margin-right: 0;
        }
    }
    .bs-1 {
        box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
    }
    .color1 {
        color: #FF4948;
    }
    .color2 {
        color: rgba(0, 0, 0, .8);
    }
    .color3 {
        color: #FAAD14;
    }
    .color4 {
        color: #FFFFFF;
    }
    .color99 {
        color: #FB9A0E;
    }
    .bgcolor-border {
        background: rgba(255, 253, 241, 1) !important;
        border: 2rpx solid #FFE58F;
    }
    .bgcolor1 {
        background: linear-gradient(270deg, rgba(255, 241, 0, 0.5) 0%, rgba(255, 249, 172, 0.25) 48%, rgba(255, 255, 255, 0.2) 100%, #FFFFFF 100%);
    }
    .bgcolor2 {
        background: linear-gradient(180deg, #FFDCDB 0%, rgba(255, 255, 255, 0) 25%);
    }
    .bgcolor3 {
        background: #FFFBE6;
    }
    .bgcolor4 {
        background: #F8F8F8;
    }
    .bgcolor5 {
        background: rgba(0, 0, 0, .23);
    }
    .bgcolor6 {
        background: linear-gradient(270deg, #FC8D55 0%, #FF4948 100%);
    }
    .border1 {
        border: 2rpx solid #FFF1B8;
    }
    .border2 {
        border: 2rpx solid #F8F8F8;
    }
    .safe-box {
        height: env(safe-area-inset-bottom);
    }
    .imgOrVedio {
        margin-right: 17rpx;
        position: relative;
        .img {
            width: 140rpx;
            height: 140rpx;
            border-radius: 8rpx;
            margin-top: 19rpx;
        }
        .videoOpen {
            position: absolute;
            top: 10rpx;
            left: 0;
            z-index: 99;
            width: 140rpx;
            height: 140rpx;
            border-radius: 8rpx;
            display: flex;
            align-items: center;
            justify-content: center;
            .video {
                z-index: 999;
                width: 140rpx;
                height: 140rpx;
            }
        }
    }
    .videoImg {
        width: 140.38rpx;
        height: 140.38rpx;
        border-radius: 7.69rpx;
        position: relative;
    }
    #myVideo {
        z-index: 1;
    }
    .zIndex999 {
        z-index: 999;
    }
    .btn-box {
        height: 120rpx;
    }
</style>
H5/pages/evaluate/service.js
New file
@@ -0,0 +1,12 @@
import request from '@/utils/request.js'
// 办理进度录入
export const saveProcess = (params) => {
    return request.post(`/api/huacheng-sangeshenbian/applet/complaint/save-process`, params, )
}
// 工单详情
export const getComplaintDetail = (params) => {
    return request.get('/api/huacheng-sangeshenbian/applet/complaint/detail', params)
}
H5/pages/index/index.vue
@@ -43,7 +43,7 @@
                    <image class="w-79 h-77 ml-38" src="/static/home/img1.png" mode=""></image>
                    <text class="ml-37 font-bold">回访评价</text>
                </view>
                <view class="pt-38 pb-38 bg1 w-333 br-19 mt-19 flex a-center" v-if="showData">
                    <image class="w-81 h-77 ml-38" src="/static/home/img8.png" mode=""></image>
                    <text class="ml-37 font-bold">统计分析</text>
@@ -102,6 +102,23 @@
            </view>
        </view>
        <popupCertificate :show="isClick" @onCancel="isClick=false"></popupCertificate>
        <!-- 用户多个角色时切换角色弹窗 -->
        <u-popup :show="changeRolePopup" round="16rpx" @close="changeRolePopup = false">
            <view class="relative">
                <image @tap.stop="changeRolePopup = false" src="@/static/closeImg.png" class="w-35 h-35 absolute"
                    style="right: 31rpx;top: 46rpx;" />
                <view class="txt-center pt-38 pb-40 fs-35 lh-48 font-bold">选择角色</view>
                <view class="lineBox mb-10"></view>
                <view style="height: 546rpx;overflow-y: auto;">
                    <view @tap.stop="changeRole(item)" v-for="(item,index) in 10" :key="index"
                        :class="index == activeRole && 'bgcolor2'"
                        class="mt-38 bgcolor1 br-58 fs-31 ml-54 mr-62 py-37 txt-center">
                        <view>XXXXXXXX管理员</view>
                    </view>
                </view>
            </view>
        </u-popup>
    </view>
</template>
@@ -134,6 +151,8 @@
                isLoading: false,
                noreadlist: [],
                noreadlists: [],
                changeRolePopup: true,
                activeRole: 1,
            }
        },
        onPullDownRefresh() {
@@ -157,6 +176,10 @@
            this.getappletcinfo()
        },
        methods: {
            changeRole(item) {
                this.activeRole = item - 1
                this.changeRolePopup = false
            },
            Allread() {
                getread().then(resp => {
@@ -294,6 +317,16 @@
    .color4 {
        color: rgba(0, 0, 0, 0.4);
    }
    .bgcolor1 {
        background: #F7F7F7;
    }
    .bgcolor2 {
        color: #fff;
        background: #FC8D55;
        box-shadow: 0rpx 4rpx 19rpx 0rpx rgba(239, 119, 58, 0.5);
    }
    .bg1 {
@@ -469,4 +502,10 @@
        color: #FFFFFF;
        font-weight: 600;
    }
    .lineBox {
        width: 100%;
        height: 1rpx;
        background: #E5E5E5;
    }
</style>
H5/pages/list/list.vue
@@ -346,7 +346,7 @@
    }
    .bgColor4 {
        background: linear-gradient(270deg, rgba(255, 241, 0, 0.5) 0%, rgba(255, 249, 172, 0.25) 48%, rgba(255, 255, 255, 0.2) 100%, #FFFFFF 100%);
        background: linear-gradient( 270deg, rgba(255,241,0,0.5) 0%, rgba(255,249,172,0.25) 48%, rgba(255,255,255,0.2) 100%, #FFFFFF 100%);
    }
    .bgColor5 {
H5/pages/problemReporting/problemReporting.vue
@@ -143,7 +143,7 @@
                display: flex;
                justify-content: space-between;
                // height: 106rpx;
                background: linear-gradient(270deg, rgba(255, 241, 0, 0.5) 0%, rgba(255, 249, 172, 0.25) 48%, rgba(255, 255, 255, 0.2) 100%, #FFFFFF 100%);
                background: linear-gradient( 270deg, rgba(255,241,0,0.5) 0%, rgba(255,249,172,0.25) 48%, rgba(255,255,255,0.2) 100%, #FFFFFF 100%);
                box-shadow: 0rpx 0rpx 27rpx 0rpx rgba(0, 0, 0, 0.1);
                border-radius: 19rpx;
                align-items: center;
H5/pages/progress/progress.vue
@@ -171,7 +171,7 @@
    }
    .bgcolor1 {
        background: linear-gradient(270deg, rgba(255, 241, 0, 0.5) 0%, rgba(255, 249, 172, 0.25) 48%, rgba(255, 255, 255, 0.2) 100%, #FFFFFF 100%);
        background: linear-gradient( 270deg, rgba(255,241,0,0.5) 0%, rgba(255,249,172,0.25) 48%, rgba(255,255,255,0.2) 100%, #FFFFFF 100%);
    }
    .bgcolor2 {
H5/pages/work-detail/postpone-apply.vue
@@ -327,7 +327,7 @@
    }
    .bgcolor1 {
        background: linear-gradient(270deg, rgba(255, 241, 0, 0.5) 0%, rgba(255, 249, 172, 0.25) 48%, rgba(255, 255, 255, 0.2) 100%, #FFFFFF 100%);
        background: linear-gradient( 270deg, rgba(255,241,0,0.5) 0%, rgba(255,249,172,0.25) 48%, rgba(255,255,255,0.2) 100%, #FFFFFF 100%);
    }
    .bgcolor2 {
H5/pages/work-detail/work-detail.vue
@@ -324,6 +324,10 @@
            <view class="btnAdd partyDown" @click="resultEntery">办理结果录入</view>
        </view>
        <!-- 党员显示 -->
        <!-- v-if="[3].includes(orderInfo.status)" -->
        <view class="btnButtom" v-if="[3].includes(orderInfo.status)">
            <view class="btnAdd  evaluate" @click.stop="toEvaluate">评价</view>
        </view>
@@ -552,6 +556,12 @@
                    url: `/pages/dispatchWorkOrder/dispatchWorkOrder?id=${this.id}`
                })
            },
            // 去评价
            toEvaluate() {
                uni.navigateTo({
                    url: `/pages/evaluate/evaluate?id=${this.id}`
                })
            },
            addProgress() {
                uni.navigateTo({
                    url: `/pages/progress/progress?id=${this.id}`
@@ -760,7 +770,7 @@
            .addressCard {
                margin: 33rpx 10rpx;
                padding: 33rpx 27rpx;
                background: linear-gradient(270deg, rgba(255, 241, 0, 0.5) 0%, rgba(255, 249, 172, 0.25) 48%, rgba(255, 255, 255, 0.2) 100%, #FFFFFF 100%);
                background: linear-gradient( 270deg, rgba(255,241,0,0.5) 0%, rgba(255,249,172,0.25) 48%, rgba(255,255,255,0.2) 100%, #FFFFFF 100%);
                border-radius: 19rpx;
                display: flex;
                justify-content: space-between;
@@ -1199,6 +1209,10 @@
            padding: 19rpx 25rpx 19rpx 25rpx !important;
        }
        .evaluate {
            padding: 19rpx 310rpx;
        }
    }
H5/static/closeImg.png
H5/static/detailImg/bg.png
H5/static/detailImg/img1.png
H5/static/detailImg/img2.png
H5/static/detailImg/img3.png
H5/static/detailImg/img4.png
H5/static/man.png
H5/static/popupBg.png
H5/static/required.png
H5/static/style/_app.scss
@@ -1216,6 +1216,9 @@
.safe-b {
    padding-bottom: env(safe-area-inset-bottom);
}
.h-safe-b{
    height: calc(env(safe-area-inset-bottom) + 10rpx);
}
.underline {
    text-decoration: underline;
}
H5/static/women.png
management/config/routes.ts
@@ -86,6 +86,33 @@
    ],
  },
  {
    path: '/party',
    // layout: false,
    name: '党员管理',
    // access: '/work_order_transaction_management',
    routes: [
      {
        name: '党员管理',
        path: '/party/manage',
        component: './party/manage/index',
        // access: '/work_order_transaction_management/work_order_item_configuration',
      },
      {
        name: '添加党员',
        path: '/party/manage/add',
        hideInMenu: true,
        component: './party/manage/components/addAndEdit',
        // access: '/work_order_transaction_management/problem_type_management',
      },
      {
        name: '党员审核',
        path: '/party/audit',
        component: './party/audit/index',
        // access: '/work_order_transaction_management/banner_management',
      },
    ],
  },
  {
    path: '/message-notification',
    // layout: false,
    name: '消息通知',
management/src/pages/party/audit/components/index.jsx
New file
@@ -0,0 +1,161 @@
import { Form, Input, Modal, Select, Upload, Space, Button, message, Row, Col, Divider } from 'antd';
import { sendRequest } from '@/utils/antdUtils';
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import { customRequest } from '@/utils/utils';
import { add, Edit, getDetail } from '../service'
const formItemLayout = {
  labelCol: { span: 8 },
  wrapperCol: { span: 12 },
};
const AddEditView = ({ visible, onSave, onUpdate, onCancel, }, ref) => {
  const [form] = Form.useForm();
  const [fileList, setFileList] = useState([])//banner图片
  const [loading, setLoading] = useState(false);
  const [editData, setEditData] = useState({})
  const formItemLayout = {
    labelCol: { span: 6 },
    wrapperCol: { span: 20 },
  };
  useImperativeHandle(ref, () => {
    return {
      refreshData: (data) => {
        setEditData(data);
        if (data.id) {
          // getDetail(data.id).then(res => {
          //   if (res.data.url) {
          //     let obj = [{
          //       uid: 1,
          //       name: 'banner',
          //       url: res.data.url
          //     }]
          //     setFileList(obj)
          //     form.setFieldsValue({ image: obj })
          //   }
          //   form.setFieldsValue({name: res.data.name})
          // })
        }
      },
      clean: () => {
        form.resetFields();
        setFileList([])
      },
    };
  });
  // 提交表单
  const submit = () => {
    form.validateFields().then(async (values) => {
      values.url = fileList[0].url
      delete values.image
      if (editData.id) {
        values.id = editData.id
        onUpdate(values)
        return
      }
      onSave(values)
    })
  }
  return (
    <Modal
      getContainer={false}
      width="65%"
      destroyOnClose
      title={'提示'}
      open={visible}
      okText='确认'
      onCancel={() => onCancel(false)}
      onOk={submit}
    >
      <div style={{ width: '100%', textAlign: 'center', margin: '20px 0', fontWeight: 'bold' }}>确认审核{editData.type == 'sure' ? '同意' : '拒绝'}所选信息么?</div>
      <Form scrollToFirstError layout="horizontal" {...formItemLayout} form={form}>
        <Row>
          <Col span={8}>
            <Form.Item
              name="name"
              label='姓名'
              required
            >
              <Input disabled placeholder='请输入'></Input>
            </Form.Item>
            <Form.Item
              name="name"
              label='所在社区'
              required
            >
              <Input disabled placeholder='请输入'></Input>
            </Form.Item>
            <Form.Item
              name="name"
              label='头像上传'
              required
            >
              <Input disabled placeholder='请输入'></Input>
            </Form.Item>
          </Col>
          <Col span={8}>
            <Form.Item
              name="name"
              label='联系电话'
              required
            >
              <Input disabled placeholder='请输入'></Input>
            </Form.Item>
            <Form.Item
              name="name"
              label='服务对象'
              required
            >
              <Input disabled placeholder='请输入'></Input>
            </Form.Item></Col>
          <Col span={8}>
            <Form.Item
              name="name"
              label='身份证号'
              required
            >
              <Input disabled placeholder='请输入'></Input>
            </Form.Item>
            <Form.Item
              name="name"
              label='所在党组织'
              required
            >
              <Input disabled placeholder='请输入'></Input>
            </Form.Item>
          </Col>
        </Row>
        {editData.type == 'refuse' && (
          <>
            <Divider />
            <Row>
              <Col span={8}>
                <Form.Item
                  name="remark"
                  label='拒绝理由'
                  rules={[{ required: true, message: '拒绝理由必填' }]}
                >
                  <Input.TextArea placeholder='请输入拒绝理由'></Input.TextArea>
                </Form.Item>
              </Col>
            </Row>
          </>
        )}
      </Form>
    </Modal>
  );
};
export default forwardRef(AddEditView);
management/src/pages/party/audit/index.jsx
New file
@@ -0,0 +1,140 @@
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { buildProTableDataSource, sendRequest, showDelConfirm } from '@/utils/antdUtils';
import { Button, message, Space,Cascader } from 'antd';
import { useRef, useState } from 'react';
import { Access, history, useAccess } from 'umi';
import AddAndEdit from './components/index';
import { getList, updateStatus, deleteBanner, add, Edit } from './service'
const Banner = () => {
  const actionRef = useRef();
  const access = useAccess();
  const addViewRef = useRef();
  const [modalVisible, handleModalVisible] = useState(false);
  const [items, setItems] = useState([]);
  const columns = [
    {
      title: '姓名',
      dataIndex: 'name'
    },
    {
      title: '性别',
      hideInSearch: true,
      dataIndex: 'name'
    },
    {
      title: '联系电话',
      hideInSearch: true,
      dataIndex: 'name'
    },
    {
      title: '身份证号',
      hideInSearch: true,
      dataIndex: 'name'
    },
    {
      title: '所在社区',
      dataIndex: 'name',
      renderFormItem: () => {
        return (
          <Cascader
            options={items}
            fieldNames={{ value: 'key', label: 'name' }}
            placeholder="请选择"
            displayRender={(label) => label[label.length - 1]}
            changeOnSelect={true}
          />
        );
      },
    },
    {
      title: '服务对象',
      dataIndex: 'name'
    },
    {
      title: '所在党组织',
      dataIndex: 'name'
    },
    {
      title: '申请时间',
      dataIndex: 'status',
      hideInSearch: true,
    },
    {
      title: '操作',
      hideInSearch: true,
      render: (text, record) => {
        return (
          <Space>
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/del']}> */}
            <Button
              type="link"
              onClick={() => {
                addViewRef.current.refreshData({type:'sure',id:record.id});
                handleModalVisible(true);
              }}
            >
              通过
            </Button>
            {/* </Access> */}
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/del']}> */}
            <Button
              type="link"
              onClick={() => {
                addViewRef.current.refreshData({type:'refuse',id:record.id});
                handleModalVisible(true);
              }}
            >
              拒绝
            </Button>
            {/* </Access> */}
          </Space >
        );
      },
    },
  ]
  return <div>
    <PageContainer title='党员审核' header={{
      breadcrumb: {},
    }}>
      <ProTable
        rowKey='id'
        actionRef={actionRef}
        columns={columns}
        pagination={{
          showSizeChanger: true,
          showQuickJumper: true,
          defaultPageSize: 10,
        }}
        request={(params) => {
          return buildProTableDataSource(getList, params)
        }}
        toolBarRender={false}
      />
      <AddAndEdit
        ref={addViewRef}
        visible={modalVisible}
        onCancel={() => handleModalVisible(false)}
        onSave={async (fileds) => {
          // const success = await sendRequest(add, fileds);
          // if (success) {
          //   handleModalVisible(false);
          //   actionRef.current.reload();
          // }
        }}
        onUpdate={async (fileds) => {
          // const success = await sendRequest(Edit, fileds);
          // if (success) {
          //   handleModalVisible(false);
          //   actionRef.current.reload();
          // }
        }}
      />
    </PageContainer>
  </div>;
};
export default Banner;
management/src/pages/party/audit/service.js
New file
@@ -0,0 +1,44 @@
import { request } from '@umijs/max';
// 列表
export const getList = async (data) => {
    return request(`/api/huacheng-sangeshenbian/banner/list`, {
        method: 'GET',
        params:data
    });
}
// 详情
export const getDetail = async (id) => {
    return request(`/api/huacheng-sangeshenbian/banner/getBannerInfo/${id}`, {
        method: 'GET',
        // data
    });
}
// 删除
export const deleteBanner = async (id) => {
    return request(`/api/huacheng-sangeshenbian/banner/delete/${id}`, {
        method: 'delete',
        // params
    });
}
// 添加 编辑
export const add = async (data) => {
    return request('/api/huacheng-sangeshenbian/banner/add', {
        method: 'POST',
        data,
    });
}
// 添加 编辑
export const Edit = async (data) => {
    return request('/api/huacheng-sangeshenbian/banner/edit', {
        method: 'POST',
        data,
    });
}
management/src/pages/party/manage/components/addAndEdit.jsx
New file
@@ -0,0 +1,232 @@
import { sendRequest } from '@/utils/antdUtils';
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
import { PageContainer, } from '@ant-design/pro-components';
import { Button, Select, Row, Col, Input, Card, Space, Form, Upload, Spin, message, Cascader, InputNumber } from 'antd';
import { useState, useEffect } from 'react';
import { add, Edit, getDetail } from '../service';
import { history, useLocation, useSearchParams } from 'umi';
import { customRequest } from '@/utils/utils';
const AddOrEditOrDetail = () => {
  const [form] = Form.useForm();
  const [loading, setLoading] = useState(false);
  const [searchParams, setSearchParams] = useSearchParams();
  const [items, setItems] = useState([]);
  const [adminLevel, setAdminLevel] = useState(1)
  const [fileList, setFileList] = useState([])
  const formItemLayout = {
    labelCol: { span: 6 },
    wrapperCol: { span: 10 },
  }
  const uploadButton = (
    <button
      style={{
        border: 0,
        background: 'none',
      }}
      type="button"
    >
      {loading ? <LoadingOutlined /> : <PlusOutlined />}
      <div
        style={{
          marginTop: 8,
        }}
      ></div>
    </button>
  );
  const config = {
    name: 'file',
    action: 'https://huacheng.psciio.com/api/huacheng-communitybackstage/communitypartybuilding/uploadimage',
    headers: {
      Authorization: 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOjE4OTI0MjE4MjgwODU4Mzc4MjYsInR5cGUiOjEsImV4cCI6MTc0MTY1OTg5MywiY3JlYXRlZCI6MTc0MDM2Mzg5MzE2MH0.o3Gc0g1LAo_kkL3X3QrC6qKwztxsp6psoTcpTreDzQUXGqPzUXw89fNSR5YKz8gzhtSuSKI2d6TJJYPX1IQCgw',
    },
  };
  useEffect(() => {
    let adminInfo = JSON.parse(localStorage.getItem('userInfo'))
    setAdminLevel(() => adminInfo.accountLevel)//角色权限1市级2区县3街道4社区5党员
  }, [])
  // 上传前
  const beforeUpload = (file, type) => {
    return new Promise(async (resolve, reject) => {
      if (file.name.includes(',')) {
        message.warning('上传图片名字不能包含英文逗号(,)');
        return Upload.LIST_IGNORE;
      }
      console.log('============================================')
      setLoading(false)
      resolve(file);
    });
  };
  const handleChange = ({ file: file, fileList: newFileList }, type) => {
    console.log(file, 'newfilelist', newFileList, 'type', type)
    if (file.status == 'error') {
      setLoading(false)
      // setFileList([])
      message.error('上传失败')
      return
    }
    if (file.status == 'done') {
      setLoading(false)
      message.success('上传成功')
    }
    let list = newFileList.map((item) => {
      if (item.status == 'done') {
        if (!item.url) {
          item.url = item.response.data;
        }
      }
      return item.url
    });
    console.log('newFileList', newFileList, 'list', list)
    // if (type == 1) {
    //   setImageUrl1(newFileList)
    // } else if (type == 2) {
    //   setImageUrl(newFileList)
    // }
  };
  const submit = () => {
    form.validateFields().then(async (values) => {
    })
  }
  const checkIdCard = (rule, value) => {
    const reg = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
    if (!reg.test(value)) {
      return Promise.reject('请输入正确的身份证号码');
    }
    return Promise.resolve();
  };
  const checkPhone = (rule, value) => {
    const reg = /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
    if (!reg.test(value)) {
      return Promise.reject('请输入正确的手机号码');
    }
    return Promise.resolve();
  };
  const checkPhoneUse = (e) => {
    console.log('eeeeeeeeee', e.target.value)
  }
  return (
    <PageContainer title={searchParams.get('detail') ? '党员详情' : searchParams.get('id') ? '编辑党员' : '添加党员'}>
      <Spin spinning={loading}>
        <Form scrollToFirstError layout="horizontal" {...formItemLayout} form={form}>
          <Card style={{ background: '#fff', paddingTop: '15px' }}>
            <Row>
              <Col span={12}>
                <Form.Item
                  name="name"
                  label='姓名'
                  rules={[{ required: true, message: '请输入党员姓名' }]}
                >
                  <Input disabled={searchParams.get('detail')} placeholder='请输入'></Input>
                </Form.Item>
                <Form.Item
                  name="name"
                  label='联系电话' rules={[{ required: true, message: '请输入党员联系电话' }, { validator: checkPhone }]}
                >
                  <Input disabled={searchParams.get('detail')} placeholder='请输入' maxLength={11} onBlur={checkPhoneUse} ></Input>
                </Form.Item>
                <Form.Item
                  name="idcard"
                  label='身份证号' rules={[{ required: true, message: '请输入党员身份证号' }, { validator: checkIdCard }]}
                >
                  <Input disabled={searchParams.get('detail')} placeholder='请输入' maxLength={18}></Input>
                </Form.Item>
                <Form.Item
                  name="name"
                  label='所在社区'
                  rules={[{ required: true, message: '请选择所在社区' }]}
                >
                  <Cascader
                    disabled={searchParams.get('detail') || adminLevel == 4}
                    options={items}
                    fieldNames={{ value: 'key', label: 'name' }}
                    placeholder="请选择"
                    displayRender={(label) => label[label.length - 1]}
                    changeOnSelect={true}
                  />
                </Form.Item>
                <Form.Item
                  name="name"
                  label='服务对象'
                //  rules={[ { required: true,message: '请输入服务对象'}]}
                >
                  <Input disabled={searchParams.get('detail')} placeholder='请输入'></Input>
                </Form.Item>
                <Form.Item
                  name="name"
                  label='所在党组织'
                //  rules={[ { required: true,message: '请输入所在党组织'}]}
                >
                  <Input disabled={searchParams.get('detail')} placeholder='请输入'></Input>
                </Form.Item>
                <Form.Item
                  name="image"
                  label="头像上传"
                  // extra={
                  //   <div>
                  //     <div>推荐尺寸732px * 320px</div>
                  //   </div>
                  // }
                  rules={[
                    {
                      required: true,
                      message: '请上传头像',
                    },
                  ]}
                >
                  <Upload
                    {...config}
                    listType="picture-card"
                    maxCount={1}
                    beforeUpload={beforeUpload}
                    onChange={handleChange}
                    onRemove={() => {
                      setFileList([])
                      form.setFieldsValue({
                        image: ''
                      })
                    }}
                    showUploadList={{
                      showPreviewIcon: false,
                    }}
                    // customRequest={customRequest}
                    accept="image/png, image/jpeg, image/jpg"
                    fileList={fileList}
                    disabled={searchParams.get('detail')}
                  >
                    {fileList?.length == 1 || searchParams.get('detail') ? null : uploadButton}
                  </Upload>
                </Form.Item>
                <div style={{ display: 'flex', justifyContent: 'center' }}>
                  <Space size='large'>
                    <Button onClick={() => history.back()}>关闭</Button>
                    {
                      !searchParams.get('detail') && <Button type='primary' onClick={submit}>确认</Button>
                    }
                  </Space>
                </div>
              </Col>
            </Row>
          </Card>
        </Form>
      </Spin>
    </PageContainer >
  );
}
export default AddOrEditOrDetail
management/src/pages/party/manage/components/export.jsx
New file
@@ -0,0 +1,81 @@
import { Form, Upload, Modal, Input, Button } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import React, { forwardRef, useImperativeHandle, useState } from 'react';
import { useEffect } from 'react';
import { downLoad } from '@/utils/utils';
const formItemLayout = {
  labelCol: { span: 4 },
  wrapperCol: { span: 18 },
};
const { TextArea } = Input;
const ImportExport = ({ visible, onSave, onCancel }, ref) => {
  const [form] = Form.useForm();
  const [status, setStatus] = useState(true);
  const okHandle = () => {
    onSave()
    // form.validateFields().then((values) => {
    //   onSave(values.file.file);
    // });
  };
  const downLod = () => {
    // downLoad('/tCheck/import-template', '检查项导入模版');
  };
  const onChange = (e) => {
    if (e.fileList && e.fileList.length > 0) {
      setStatus(false);
    } else {
      setStatus(true);
    }
  };
  useImperativeHandle(ref, () => {
    return {
      refreshData: (data) => {},
      clean: () => {
        form.resetFields();
      },
    };
  });
  return (
    <Modal
      getContainer={false}
      width="30%"
      destroyOnClose
      title={'导入党员信息'}
      open={visible}
      okText="立即导入"
      onCancel={() => onCancel(false)}
      onOk={okHandle}
    >
      <Form layout="horizontal" {...formItemLayout} form={form}>
        <div style={{ width: '100%', textAlign: 'end', marginBottom: '32px' }}>
          <a
            onClick={() => {   downLod();}}
          >
            模版下载
          </a>
        </div>
        <Form.Item name="file" label="导入文件" rules={[{ required: true, message: '请上传文件' }]}>
          <Upload
            name="file"
            maxCount="1"
            listType="text"
            accept=".xls,.xlsx,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            onChange={(e) => {
              onChange(e);
            }}
            showUploadList={true}
          >
            {status && <Button icon={<UploadOutlined />}>去选择</Button>}
          </Upload>
        </Form.Item>
      </Form>
    </Modal>
  );
};
export default forwardRef(ImportExport);
management/src/pages/party/manage/components/index.jsx
New file
@@ -0,0 +1,100 @@
import { Form, Input, Modal, Select, Upload, Space, Button, message } from 'antd';
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { forwardRef, useEffect, useImperativeHandle, useState,useRef } from 'react';
const AddEditView = ({ visible, onSave, onUpdate, onCancel, }, ref) => {
  const actionRef = useRef();
  const [tableListData, setTableListData] = useState([])
  const columns = [
    {
      title: '姓名',
      dataIndex: 'name'
    },
    {
      title: '联系电话',
      hideInSearch: true,
      dataIndex: 'name'
    },
    {
      title: '身份证号',
      dataIndex: 'name'
    },
    {
      title: '所在社区',
      dataIndex: 'name',
    },
    {
      title: '服务对象',
      dataIndex: 'name'
    },
    {
      title: '所在党组织',
      dataIndex: 'name'
    },
    {
      title: '失败原因',
      dataIndex: 'status',
    },
  ]
  useImperativeHandle(ref, () => {
    return {
      refreshData: (data) => {
      },
      clean: () => {
      },
    };
  });
  // 提交表单
  const submit = () => {
  }
  return (
    <Modal
      getContainer={false}
      width="65%"
      destroyOnClose
      title={'数据导入失败提示'}
      open={visible}
      onCancel={() => onCancel(false)}
      footer={
        [
          <Button
            key="submit"
            type="primary"
            onClick={() => onCancel(false)}
          >
            确认
          </Button>,
        ]
      }
    >
      <div>
        <div style={{width:'100%',textAlign:'center',marginBottom:'20px',fontWeight:'bold'}}>以下信息导入失败</div>
        <ProTable
        rowKey='id'
        search={false}
        actionRef={actionRef}
        columns={columns}
        dataSource={tableListData}
        pagination={{
          showSizeChanger: true,
          showQuickJumper: true,
          defaultPageSize: 10,
        }}
        toolBarRender={false}
      />
      </div>
    </Modal>
  );
};
export default forwardRef(AddEditView);
management/src/pages/party/manage/index.jsx
New file
@@ -0,0 +1,237 @@
import { PageContainer, ProTable } from '@ant-design/pro-components';
import { buildProTableDataSource, sendRequest, showDelConfirm } from '@/utils/antdUtils';
import { Button, message, Space, Cascader } from 'antd';
import { useRef, useState } from 'react';
import { Access, history, useAccess } from 'umi';
import AddAndEdit from './components/index';
import ImportExcell from './components/export';
import { getList, updateStatus, deleteBanner, add, Edit } from './service'
import { exportExcell } from '@/utils/utils'
const Banner = () => {
  const actionRef = useRef();
  const access = useAccess();
  const addViewRef = useRef();
  const [modalVisible, handleModalVisible] = useState(false);
  const [items, setItems] = useState([]);
  const [excelParams, setExcelParams] = useState({});
  const [modalExport, handleModalExport] = useState(false);
  const columns = [
    {
      title: '姓名',
      dataIndex: 'name'
    },
    {
      title: '性别',
      hideInSearch: true,
      dataIndex: 'name'
    },
    {
      title: '所在社区',
      dataIndex: 'name',
      renderFormItem: () => {
        return (
          <Cascader
            options={items}
            fieldNames={{ value: 'key', label: 'name' }}
            placeholder="请选择"
            displayRender={(label) => label[label.length - 1]}
            changeOnSelect={true}
          />
        );
      },
    },
    {
      title: '服务对象',
      dataIndex: 'name'
    },
    {
      title: '所在党组织',
      dataIndex: 'name'
    },
    {
      title: '状态',
      dataIndex: 'status',
      valueEnum: {
        0: { text: '全部' },
        1: { text: '正常中' },
        2: { text: '已冻结' },
      }
    },
    {
      title: '操作',
      hideInSearch: true,
      render: (text, record) => {
        return (
          <Space>
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/edit']}> */}
            <Button
              type="link"
              onClick={() => {
                history.push(`/party/manage/add?type=edit&id=${record.id}`)
              }}
            >
              编辑
            </Button>
            {/* </Access> */}
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/del']}> */}
            <Button
              type="link"
              onClick={() => {
                showDelConfirm(async () => {
                  // let status = await sendRequest(deleteBanner, record.id)
                  // if (status) {
                  //   actionRef.current.reload();
                  // }
                }, '确认删除所选信息吗?');
              }}
            >
              删除
            </Button>
            {/* </Access> */}
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/del']}> */}
            <Button
              type="link"
              onClick={() => {
                history.push(`/party/manage/add?detail=true&id=${record.id}`)
              }}
            >
              查看详情
            </Button>
            {/* </Access> */}
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/del']}> */}
            <Button
              type="link"
              onClick={() => {
                showDelConfirm(async () => {
                  // let status = await sendRequest(deleteBanner, record.id)
                  // if (status) {
                  //   actionRef.current.reload();
                  // }
                }, '确认冻结该党员信息吗?');
              }}
            >
              冻结
            </Button>
            {/* </Access> */}
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/del']}> */}
            <Button
              type="link"
              onClick={() => {
                showDelConfirm(async () => {
                  // let status = await sendRequest(deleteBanner, record.id)
                  // if (status) {
                  //   actionRef.current.reload();
                  // }
                }, '确认解冻该党员信息吗?');
              }}
            >
              解冻
            </Button>
            {/* </Access> */}
          </Space >
        );
      },
    },
  ]
  return <div>
    <PageContainer title='党员管理' header={{
      breadcrumb: {},
    }}>
      <ProTable
        rowKey='id'
        actionRef={actionRef}
        columns={columns}
        pagination={{
          showSizeChanger: true,
          showQuickJumper: true,
          defaultPageSize: 10,
        }}
        request={(params) => {
          params.status = (params.status && params.status != 0) ? params.status : '';
          setExcelParams(() => params)
          return buildProTableDataSource(getList, params)
        }}
        toolBarRender={(action, selectRows) => [
          <Space>
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/add']}> */}
            <Button
              type="primary"
              onClick={() => {
                history.push('/party/manage/add?type=add')
              }}
            >
              添加
            </Button>
            {/* </Access> */}
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/add']}> */}
            <Button
              type="primary"
              onClick={() => {
                // exportExcell('党员列表', excelParams, '/promotion/mgt/coupon/receive-detail/export')
              }}
            >
              导出
            </Button>
            {/* </Access> */}
            {/* <Access accessible={access['/work_order_transaction_management/banner_management/add']}> */}
            <Button
              type="primary"
              onClick={() => {
                // history.push('/party/manage/add?type=add')
                handleModalExport(true)
              }}
            >
              导入
            </Button>
            {/* </Access> */}
          </Space>
        ]}
      />
      <AddAndEdit
        ref={addViewRef}
        visible={modalVisible}
        onCancel={() => handleModalVisible(false)}
        onSave={async (fileds) => {
          // const success = await sendRequest(add, fileds);
          // if (success) {
            handleModalVisible(false);
          //   actionRef.current.reload();
          // }
        }}
        onUpdate={async (fileds) => {
          // const success = await sendRequest(Edit, fileds);
          // if (success) {
            handleModalVisible(false);
          //   actionRef.current.reload();
          // }
        }}
      />
      <ImportExcell
        visible={modalExport}
        onSave={async (fileds) => {
          console.log('上传文件数据', fileds);
          handleModalExport(false);
          handleModalVisible(true)
          // const success = await sendRequest(enable, fileds);
          // if (success) {
          //   handleModalExport(false);
          //   // actionRef.current.reload();
          //   // listCheck({ checkType: checktype, }).then(res => {
          //   //   console.log('一键导入数据', res)
          //   // })
          // }
        }}
        onCancel={() => handleModalExport(false)}
      />
    </PageContainer>
  </div>;
};
export default Banner;
management/src/pages/party/manage/service.js
New file
@@ -0,0 +1,44 @@
import { request } from '@umijs/max';
// 列表
export const getList = async (data) => {
    return request(`/api/huacheng-sangeshenbian/banner/list`, {
        method: 'GET',
        params:data
    });
}
// 详情
export const getDetail = async (id) => {
    return request(`/api/huacheng-sangeshenbian/banner/getBannerInfo/${id}`, {
        method: 'GET',
        // data
    });
}
// 删除
export const deleteBanner = async (id) => {
    return request(`/api/huacheng-sangeshenbian/banner/delete/${id}`, {
        method: 'delete',
        // params
    });
}
// 添加 编辑
export const add = async (data) => {
    return request('/api/huacheng-sangeshenbian/banner/add', {
        method: 'POST',
        data,
    });
}
// 添加 编辑
export const Edit = async (data) => {
    return request('/api/huacheng-sangeshenbian/banner/edit', {
        method: 'POST',
        data,
    });
}