Browse Source

app端宣传阵地

pengjing 10 months ago
parent
commit
2f6a4d39fd
32 changed files with 1559 additions and 92 deletions
  1. 53 0
      parth5/parth5/src/app/api/propagandawork/position/index.ts
  2. 44 0
      parth5/parth5/src/app/api/propagandawork/position/panel/index.ts
  3. 20 3
      parth5/parth5/src/app/app.scss
  4. 1 0
      parth5/parth5/src/app/comm/modal/bimage/bimage.component.html
  5. 7 0
      parth5/parth5/src/app/comm/modal/bimage/bimage.component.scss
  6. 75 0
      parth5/parth5/src/app/comm/modal/bimage/bimage.component.ts
  7. 42 75
      parth5/parth5/src/app/comm/modal/imglist/imglist.component.ts
  8. 16 0
      parth5/parth5/src/app/routes/propagandawork/position.ts
  9. 2 2
      parth5/parth5/src/app/views/pages/partyuser/party-dues/detail/detail.component.html
  10. 3 3
      parth5/parth5/src/app/views/pages/partyuser/party-dues/edit/edit.component.html
  11. 0 4
      parth5/parth5/src/app/views/pages/partyuser/party-dues/edit/edit.component.scss
  12. 96 0
      parth5/parth5/src/app/views/pages/propagandawork/position/detail/detail.component.html
  13. 38 0
      parth5/parth5/src/app/views/pages/propagandawork/position/detail/detail.component.scss
  14. 137 0
      parth5/parth5/src/app/views/pages/propagandawork/position/detail/detail.component.ts
  15. 101 0
      parth5/parth5/src/app/views/pages/propagandawork/position/edit/edit.component.html
  16. 31 0
      parth5/parth5/src/app/views/pages/propagandawork/position/edit/edit.component.scss
  17. 208 0
      parth5/parth5/src/app/views/pages/propagandawork/position/edit/edit.component.ts
  18. 55 0
      parth5/parth5/src/app/views/pages/propagandawork/position/panel/detail/detail.component.html
  19. 34 0
      parth5/parth5/src/app/views/pages/propagandawork/position/panel/detail/detail.component.scss
  20. 103 0
      parth5/parth5/src/app/views/pages/propagandawork/position/panel/detail/detail.component.ts
  21. 43 0
      parth5/parth5/src/app/views/pages/propagandawork/position/panel/edit/edit.component.html
  22. 38 0
      parth5/parth5/src/app/views/pages/propagandawork/position/panel/edit/edit.component.scss
  23. 52 0
      parth5/parth5/src/app/views/pages/propagandawork/position/panel/edit/edit.component.ts
  24. 52 0
      parth5/parth5/src/app/views/pages/propagandawork/position/position.component.html
  25. 42 0
      parth5/parth5/src/app/views/pages/propagandawork/position/position.component.scss
  26. 171 0
      parth5/parth5/src/app/views/pages/propagandawork/position/position.component.ts
  27. 3 1
      parth5/parth5/src/app/views/tapp/tab-main/tab-main.module.ts
  28. 3 1
      parth5/parth5/src/app/views/tapp/tab-main/tab-main.route.ts
  29. 5 1
      src/main/java/com/ghsc/partybuild/controller/app/AppPublicityController.java
  30. 2 0
      src/main/java/com/ghsc/partybuild/service/PublicityService.java
  31. 80 1
      src/main/java/com/ghsc/partybuild/service/impl/PublicityServiceImpl.java
  32. 2 1
      src/main/resources/mapping/PublicityCQuery.xml

+ 53 - 0
parth5/parth5/src/app/api/propagandawork/position/index.ts

@@ -0,0 +1,53 @@
+import {ConfigService, RequsetData} from "../../../service/config.service";
+import {Injectable} from "@angular/core";
+import {Observable} from "rxjs";
+import {UserService} from "../../../service/user.service";
+
+export interface reqParams {
+  pageIndex: number,
+  pageSize: number,
+  dzzdm: string,
+  positionName: string,
+  positionType: number,
+  positionLevel: number,
+  positionState: number,
+  startDate: string,
+  endDate: string
+}
+
+@Injectable({providedIn: 'root'})
+export class PositionApi {
+  constructor(private configService: ConfigService, private userService: UserService) {
+  }
+
+  getList(params: reqParams): Observable<RequsetData> {
+    return this.configService.HttpGetRomote('/appApi/publicity/getPositionList', params);
+  }
+
+  delete(id: string): Observable<RequsetData> {
+    return this.configService.HttpGetRomote('/appApi/publicity/deletePositionById', {
+      id: id,
+    });
+  }
+
+  getData(id: string, dzzdm: string) {
+    return this.configService.HttpGetRomote('/appApi/publicity/getPositionById', {id: id, dzzdm: dzzdm});
+  }
+
+  deletePlan(id: string) {
+    return this.configService.HttpGetRomote('/app/appApi/publicity/deletePanel', {
+      id: id,
+    });
+  }
+
+  save(data: any, panelList: any): Observable<RequsetData> {
+    return this.configService.HttpPostRomote('/appApi/publicity/savePosition', {
+      dataModel: data,
+      userId: this.userService.GetUser().userid,
+      userName: this.userService.GetUser().username,
+      panelList: JSON.stringify(panelList)
+    });
+  }
+
+}
+

+ 44 - 0
parth5/parth5/src/app/api/propagandawork/position/panel/index.ts

@@ -0,0 +1,44 @@
+import {Injectable} from "@angular/core";
+import {Observable} from "rxjs";
+import {UserService} from "../../../../service/user.service";
+import {ConfigService, RequsetData} from "../../../../service/config.service";
+
+export interface reqParams {
+  pageIndex: number,
+  pageSize: number,
+  positionId: string
+
+}
+
+@Injectable({providedIn: 'root'})
+export class PanelApi {
+  constructor(private configService: ConfigService, private userService: UserService) {
+  }
+
+  getList(params: reqParams): Observable<RequsetData> {
+    return this.configService.HttpGetRomote('/appApi/publicity/getPanelRecordList', params);
+  }
+
+  delete(id: string): Observable<RequsetData> {
+    return this.configService.HttpGetRomote('/appApi/publicity/deletePositionById', {
+      id: id,
+    });
+  }
+
+  getData(panelId: string, positionId: string) {
+    return this.configService.HttpGetRomote('/appApi/publicity/getPanelById', {
+      panelId: panelId,
+      positionId: positionId
+    });
+  }
+
+  save(data: any): Observable<RequsetData> {
+    return this.configService.HttpPostRomote('/appApi/publicity/savePanel', {
+      dataModel: data,
+      userId: this.userService.GetUser().userid,
+      userName: this.userService.GetUser().username,
+    });
+  }
+
+}
+

+ 20 - 3
parth5/parth5/src/app/app.scss

@@ -1,8 +1,8 @@
 // App Styles
 // ----------------------------------------------------------------------------
-// Put style rules here that you want to apply to the entire application. These 
-// styles are for the entire app and not just one component. Additionally, this 
-// file can hold Sass mixins, functions, and placeholder classes to be imported 
+// Put style rules here that you want to apply to the entire application. These
+// styles are for the entire app and not just one component. Additionally, this
+// file can hold Sass mixins, functions, and placeholder classes to be imported
 // and used throughout the application.
 @import "~photoswipe/dist/photoswipe.css";
 @import "~photoswipe/dist/default-skin/default-skin.css";
@@ -498,3 +498,20 @@ background: white;
 .filter-option{
   min-height: 55px;
 }
+
+.footer-btn{
+  display: flex;
+  text-align: center;
+  margin: 20px;
+  ion-button{
+    width: 100%;
+    height: 35px;
+  }
+}
+
+ion-list {
+  ion-item{
+    --inner-padding-top: 8px;
+    --inner-padding-bottom: 8px;
+  }
+}

+ 1 - 0
parth5/parth5/src/app/comm/modal/bimage/bimage.component.html

@@ -0,0 +1 @@
+<img [src]="imgModel.trustUrl" (click)="showBigImage()" onerror="this.src='assets/icon/nopic.png';this.classList.remove('item-img')"/>

+ 7 - 0
parth5/parth5/src/app/comm/modal/bimage/bimage.component.scss

@@ -0,0 +1,7 @@
+img{
+  object-fit: cover;
+  margin-right: 10px;
+  border-radius: 8px;
+  height: 100%;
+  width: 100%;
+}

+ 75 - 0
parth5/parth5/src/app/comm/modal/bimage/bimage.component.ts

@@ -0,0 +1,75 @@
+import {Component, Input, OnInit, ViewChild} from '@angular/core';
+import {FileApi} from "../../../api/file";
+import {RequsetData} from "../../../service/config.service";
+import {DomSanitizer} from '@angular/platform-browser';
+import {PhotoSwipeComponent} from "../photo-swipe/photo-swipe.component";
+import {AlertModal} from "../alert";
+
+@Component({
+  selector: 'app-bimage',
+  templateUrl: './bimage.component.html',
+  styleUrls: ['./bimage.component.scss'],
+})
+export class BimageComponent implements OnInit {
+  @ViewChild(PhotoSwipeComponent)
+  photoSwipe: PhotoSwipeComponent;
+
+  @Input() fileid: string = '';
+
+  imgModel: any = {
+    fileid: ''
+  };
+
+  constructor(private fileApi: FileApi, private sanitizer: DomSanitizer, private alertModal: AlertModal) {
+  }
+
+  ngOnInit() {
+    this.getImgBase64();
+  }
+
+  getImgBase64() {
+    this.fileApi.getImageBase64(this.fileid).subscribe((data: RequsetData) => {
+      if (data.success && data.item != null) {
+        this.imgModel.base64 = "data:image/png;base64," + data.item.base64;
+        this.imgModel.height = data.item.height;
+        this.imgModel.width = data.item.width;
+        this.imgModel.blobUrl = URL.createObjectURL(this.base64ToBlob(this.imgModel.base64));
+        this.imgModel.trustUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.imgModel.blobUrl);
+      }
+    });
+  }
+
+  base64ToBlob(data) {
+    var arr = data.split(','),
+      mime = arr[0].match(/:(.*?);/)[1],
+      bstr = atob(arr[1]),
+      n = bstr.length,
+      u8arr = new Uint8Array(n);
+
+    while (n--) {
+      u8arr[n] = bstr.charCodeAt(n);
+    }
+    return new Blob([u8arr], {type: mime});
+  }
+
+
+  showBigImage() {
+    try {
+      var items = [];
+
+      items.push({
+        src: this.imgModel.blobUrl,
+        w: this.imgModel.width || 500,
+        h: this.imgModel.height || 300
+      });
+
+      this.photoSwipe.open(items, {
+        index: 0,
+        tapToClose: true
+      }, "pswp" + (Math.random() * 100000).toFixed(0).toString());
+    } catch (e) {
+      this.alertModal.alert("图片查看异常:" + e);
+    }
+  }
+
+}

+ 42 - 75
parth5/parth5/src/app/comm/modal/imglist/imglist.component.ts

@@ -1,11 +1,12 @@
 import {Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
 import {ConfigService, RequsetData} from "../../../service/config.service";
 import {UserService} from "../../../service/user.service";
-import {ActionSheetController, AlertController, LoadingController} from "@ionic/angular";
+import {ActionSheetController} from "@ionic/angular";
 import {PhotoSwipeComponent} from "../photo-swipe/photo-swipe.component";
 import {base64File, FileApi} from "../../../api/file";
 import {Camera, CameraResultType, CameraSource} from "@capacitor/camera";
 import {DomSanitizer} from '@angular/platform-browser';
+import {AlertModal} from "../alert";
 
 @Component({
   selector: 'app-imglist',
@@ -31,9 +32,8 @@ export class ImglistComponent implements OnInit {
   loading: any = null;
   imgExt = ['.jpg', '.bmp', '.png', '.gif', '.jpe', '.jpeg'];
 
-  constructor(private configService: ConfigService, private userService: UserService, public alertController: AlertController,
-              public loadingController: LoadingController, private actionSheetController: ActionSheetController
-    , private fileApi: FileApi, private sanitizer: DomSanitizer) {
+  constructor(private configService: ConfigService, private userService: UserService, private actionSheetController: ActionSheetController
+    , private fileApi: FileApi, private sanitizer: DomSanitizer, private alertModal: AlertModal) {
   }
 
   ngOnInit() {
@@ -81,7 +81,7 @@ export class ImglistComponent implements OnInit {
 
   //删除图片
   removeImg(id) {
-    this.presentAlertConfirm("确认删除?", () => {
+    this.alertModal.confirm("确认删除?", () => {
       this.fileApi.delete(id).subscribe((fdata: RequsetData) => {
         if (fdata.success) {
           /*this.getImgList();*/
@@ -110,7 +110,7 @@ export class ImglistComponent implements OnInit {
         tapToClose: true
       }, "pswp" + (Math.random() * 100000).toFixed(0).toString());
     } catch (e) {
-      this.presentAlert("图片查看异常:" + e);
+      this.alertModal.alert("图片查看异常:" + e);
     }
   }
 
@@ -202,77 +202,44 @@ export class ImglistComponent implements OnInit {
       isImage: true
     }
 
-    await thisComponent.presentLoading('正在上传,请稍等...', 2000);
-
-    if (!thisComponent.imgOption.isMulti) {
-      thisComponent.fileApi.deleteByRefId(fileModel.fileRefId, fileModel.fileType).subscribe((data: RequsetData) => {
-        if (data.success) {
-          thisComponent.imgList = [];
-
-          thisComponent.fileApi.uploadFileBase64(fileModel).subscribe((data: RequsetData) => {
-            if (data.success) {
-              thisComponent.presentAlert("上传成功");
-              thisComponent.getImgList();
-            } else {
-              thisComponent.presentAlert(data.msg);
-            }
-          });
-        } else {
-          thisComponent.presentAlert("原文件删除失败!" + data.msg);
-        }
-      });
-    } else {
-      thisComponent.fileApi.uploadFileBase64(fileModel).subscribe((data: RequsetData) => {
-        if (data.success) {
-          thisComponent.presentAlert("上传成功");
-          thisComponent.getImgList();
-        } else {
-          thisComponent.presentAlert(data.msg);
-        }
-      });
-    }
-  }
-
-  async presentAlert(msg: string) {
-    const alert = await this.alertController.create({
-      header: '提示',
-      subHeader: '',
-      message: msg,
-      buttons: ['确定']
-    });
-
-    await alert.present();
-  }
-
-  async presentAlertConfirm(msg: string, handler) {
-    const alert = await this.alertController.create({
-      header: '提示',
-      message: '<strong>' + msg + '</strong>',
-      buttons: [
-        {
-          text: '取消',
-          role: 'cancel',
-          cssClass: 'secondary',
-          handler: () => {
-
+    thisComponent.alertModal.loading('正在上传,请稍等...').then((loading) => {
+      if (!thisComponent.imgOption.isMulti) {
+        thisComponent.fileApi.deleteByRefId(fileModel.fileRefId, fileModel.fileType).subscribe((data: RequsetData) => {
+          if (data.success) {
+            thisComponent.imgList = [];
+
+            thisComponent.fileApi.uploadFileBase64(fileModel).subscribe((data: RequsetData) => {
+              loading.dismiss();
+              if (data.success) {
+                thisComponent.alertModal.alert("上传成功");
+                thisComponent.getImgList();
+              } else {
+                thisComponent.alertModal.alert(data.msg);
+              }
+            }, () => {
+              loading.dismiss();
+            });
+          } else {
+            loading.dismiss();
+            thisComponent.alertModal.alert("原文件删除失败!" + data.msg);
           }
-        }, {
-          text: '确定',
-          handler: handler
-        }
-      ]
-    });
-
-    await alert.present();
-  }
-
-  async presentLoading(msg: string, duration: number) {
-    this.loading = await this.loadingController.create({
-      message: msg,
-      spinner: 'circles',
-      duration: duration
+        }, () => {
+          loading.dismiss();
+        });
+      } else {
+        thisComponent.fileApi.uploadFileBase64(fileModel).subscribe((data: RequsetData) => {
+          loading.dismiss();
+          if (data.success) {
+            thisComponent.alertModal.alert("上传成功");
+            thisComponent.getImgList();
+          } else {
+            thisComponent.alertModal.alert(data.msg);
+          }
+        }, () => {
+          loading.dismiss();
+        });
+      }
     });
-    return this.loading.present();
   }
 
 }

+ 16 - 0
parth5/parth5/src/app/routes/propagandawork/position.ts

@@ -0,0 +1,16 @@
+import {Routes} from "@angular/router";
+import {PositionComponent} from "../../views/pages/propagandawork/position/position.component";
+import {EditComponent} from "../../views/pages/propagandawork/position/edit/edit.component";
+import {DetailComponent} from "../../views/pages/propagandawork/position/detail/detail.component";
+import {EditComponent as PanelEditComponent} from "../../views/pages/propagandawork/position/panel/edit/edit.component";
+import {DetailComponent as PanelDetailComponent} from "../../views/pages/propagandawork/position/panel/detail/detail.component";
+
+const routes: Routes = [
+  {path: 'propagandawork/position', component: PositionComponent},
+  {path: 'propagandawork/position/edit', component: EditComponent},
+  {path: 'propagandawork/position/detail', component: DetailComponent},
+  {path: 'propagandawork/position/panel/edit', component: PanelEditComponent},
+  {path: 'propagandawork/position/panel/detail', component: PanelDetailComponent}
+];
+
+export default routes;

+ 2 - 2
parth5/parth5/src/app/views/pages/partyuser/party-dues/detail/detail.component.html

@@ -30,12 +30,12 @@
         <ion-input #specialexpenses="ngModel" name="specialexpenses" id="specialexpenses" [(ngModel)]="detailModel.specialexpenses"></ion-input>
       </ion-item>-->
     </ion-list>
-    <ion-toolbar class="toolbar-center">
+    <div class="footer-btn">
       <ion-button slot="end" color="danger" mode="ios"
                   (click)="save()" [disabled]="!dataForm.form.valid">
         提交
       </ion-button>
-    </ion-toolbar>
+    </div>
   </form>
 </ion-content>
 

+ 3 - 3
parth5/parth5/src/app/views/pages/partyuser/party-dues/edit/edit.component.html

@@ -63,11 +63,11 @@
   <ion-item *ngIf="dataList.length==0" style="text-align: center;">
     <ion-label><p>暂无数据</p></ion-label>
   </ion-item>
-  <ion-toolbar class="toolbar-center">
+  <div class="footer-btn">
     <ion-button slot="end" color="danger" mode="ios"
-                (click)="save()" class="submitBtn">
+                (click)="save()">
       提交
     </ion-button>
-  </ion-toolbar>
+  </div>
 </ion-content>
 

+ 0 - 4
parth5/parth5/src/app/views/pages/partyuser/party-dues/edit/edit.component.scss

@@ -68,7 +68,3 @@ ion-grid {
 app-partyselect{
   width: 75%;
 }
-
-.submitBtn{
-  width: 100%;margin: 20px;
-}

+ 96 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/detail/detail.component.html

@@ -0,0 +1,96 @@
+<ion-header class="header-theme2">
+  <ion-toolbar>
+    <ion-label class="title-center">宣传阵地信息详情</ion-label>
+    <ion-buttons slot="start">
+      <ion-back-button icon="ios-back2" mode="md"></ion-back-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content>
+  <form class="form-table">
+    <ion-item>
+      <ion-label>阵地名称</ion-label>
+      <ion-text>{{dataModel.positionname}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>所属党组织</ion-label>
+      <ion-text>{{dataModel.partyname}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>阵地类别</ion-label>
+      <ion-text>{{dataModel.positiontypename}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>等级</ion-label>
+      <ion-text>{{dataModel.positionlevelname}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>编号</ion-label>
+      <ion-text>{{dataModel.positioncode}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>位置</ion-label>
+      <ion-text>{{dataModel.address}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>尺寸</ion-label>
+      <ion-text>{{dataModel.sizes}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>建设时间</ion-label>
+      <ion-text>{{dataModel.buildtime | date:'yyyy-MM-dd'}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>责任人</ion-label>
+      <ion-text>{{dataModel.headusername}}</ion-text>
+    </ion-item>
+    <!--<ion-item>
+      <ion-label>状态</ion-label>
+      <ion-text>{{dataModel.positionstatename}}</ion-text>
+    </ion-item>-->
+    <ion-item>
+      <ion-label>宣传标语</ion-label>
+      <ion-text>{{panelModel.TITLE}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>更新时间</ion-label>
+      <ion-text>{{panelModel.PANELTIME | date:'yyyy-MM-dd'}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>宣传备注</ion-label>
+      <ion-text>{{panelModel.REMARK}}</ion-text>
+    </ion-item>
+    <ion-item mode="md" [ngClass]="{'border-none': panelList.length>0}">
+      <ion-label>阵地图片</ion-label>
+      <ion-text style="color: #998989 !important;">{{panelList.length>0?(panelList[0].PANELTIME | date:'yyyy-MM-dd'):'无更新记录'}}</ion-text>
+      <ion-icon *ngIf="userInfo.userid==dataModel.createuserid" slot="end" (click)="addPanel()"  name="add-circle-outline" size="large" color="danger"></ion-icon>
+    </ion-item>
+    <ion-item mode="md" *ngIf="panelList.length>0">
+      <ion-label></ion-label>
+      <div *ngIf="panelList.length>0"  style="width: 70%">
+        <img src="{{webServerHost}}/appApi/home/showImg/{{panelList[0].PANELIMG}}"
+             onerror="this.src='assets/icon/nopic.png';this.classList.remove('item-img')"
+             (click)="showBigImage(panelList[0].PANELIMG)"
+             style="width: 100%;height: 100px;"/>
+      </div>
+    </ion-item>
+    <!--<ion-item style="&#45;&#45;inner-border-width: 0px 0px 0px 0px;">
+      <ion-label>图片</ion-label>
+    </ion-item>
+    <app-imglist [(imgOption)]="imgOption"></app-imglist>-->
+  </form>
+  <!--<ion-item *ngIf="panelList.length>0" (click)="detailOpen=!detailOpen" class="item-detail" [ngClass]="detailOpen?'detail-open':'detail-close'" detail style="&#45;&#45;inner-border-width: 0px 0px 0px 0px;">
+    <div class="line-y"></div>
+    阵地更新记录
+  </ion-item>
+  <ion-list *ngIf="detailOpen">
+    <ion-item *ngFor="let item of panelList" [routerLink]="['../panelDetail']" [queryParams]="{panelId:item.PANELID,positionId:dataModel.publicitypositionid,type:2}" style="&#45;&#45;inner-border-width: 0px 0px 0px 0px;">
+      <img src="{{webServerHost}}/appApi/home/showImg/{{item.PANELIMG}}" class="item-img" onerror="this.src='assets/icon/nopic.png';this.classList.remove('item-img')"/>
+      <ion-label>
+        <h2>{{item.TITLE}}</h2>
+        <p>{{item.PARTYNAME}}</p>
+      </ion-label>
+    </ion-item>
+  </ion-list>-->
+</ion-content>
+<app-photo-swipe></app-photo-swipe>

+ 38 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/detail/detail.component.scss

@@ -0,0 +1,38 @@
+ion-content{
+  z-index: 11;
+}
+
+ion-item {
+  --inner-border-width: 0px 0px 1px 0px;
+  margin-right: 10px;
+}
+
+.detail-open::part(detail-icon){
+  transform: rotate(90deg);
+  transition: transform 0.2s ease-out;
+}
+
+.detail-close::part(detail-icon){
+  transform: rotate(0deg);
+  transition: transform 0.2s ease-out;
+}
+
+ion-item{
+  img{
+    margin-right: 10px;
+    border-radius: 8px;
+    width: 80px;
+    height: 50px;
+  }
+  .item-img{
+    object-fit: cover;
+  }
+}
+
+.item-detail{
+  margin: 0px !important;
+}
+
+.border-none{
+  --inner-border-width: 0px !important;
+}

+ 137 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/detail/detail.component.ts

@@ -0,0 +1,137 @@
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {DatePipe} from "@angular/common";
+import {ActivatedRoute, Router} from "@angular/router";
+import {AlertController, LoadingController, ModalController} from "@ionic/angular";
+import {PhotoSwipeComponent} from "../../../../../comm/modal/photo-swipe/photo-swipe.component";
+import {ConfigService, RequsetData} from "../../../../../service/config.service";
+import {UserService} from "../../../../../service/user.service";
+import {PositionApi} from "../../../../../api/propagandawork/position";
+import {AlertModal} from "../../../../../comm/modal/alert";
+import {PanelApi} from "../../../../../api/propagandawork/position/panel";
+
+@Component({
+  selector: 'app-detail',
+  templateUrl: './detail.component.html',
+  styleUrls: ['./detail.component.scss'],
+})
+export class DetailComponent implements OnInit {
+
+  @ViewChild(PhotoSwipeComponent)
+  photoSwipe: PhotoSwipeComponent;
+
+  userInfo: any = {};
+  loading: any = null;
+  getDataUrl: string = '/appApi/publicity/getPositionInfoById';
+  getPanelListUrl: string = '/appApi/publicity/getPanelRecordList';
+  dataModel: any = {};
+  panelList: any = [];
+  detailOpen: boolean = false;
+  webServerHost: string = '';
+  panelModel: any = {};
+  imgOption: any = {
+    fileRefid: '',
+    fileName: '',
+    fileType: 4,
+    isMulti: true,
+    readonly: true
+  };
+
+  constructor(private datePipe: DatePipe, private router: Router, private routeInfo: ActivatedRoute, private configService: ConfigService, private userService: UserService
+    , public modalController: ModalController, private positionApi: PositionApi, private alertModal: AlertModal, private panelApi: PanelApi) {
+  }
+
+  ngOnInit() {
+    this.userInfo = this.userService.GetUser();
+    this.routeInfo.queryParams.subscribe(params => {
+      this.dataModel.id = params['id'];
+      this.imgOption.fileRefid = params['panelid'];
+      this.getData();
+    });
+
+    this.configService.GetConfig().subscribe((config) => {
+      this.webServerHost = config.webServerHost;
+    });
+  }
+
+  getData() {
+    this.positionApi.getData(
+      this.dataModel.id,
+      this.userService.GetUser().DZZDM
+    ).subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.dataModel = data.item;
+        this.getPanelList();
+      }
+    });
+  }
+
+  getPanelList() {
+    this.panelApi.getList({
+      pageIndex: 1, pageSize: 100, positionId: this.dataModel.publicitypositionid
+    }).subscribe((data: RequsetData) => {
+      if (data.success) {
+        if (data.item.list.length > 0) {
+          this.panelModel = data.item.list[0];
+          this.imgOption.fileRefid = this.panelModel.PANELID;
+          this.panelList = data.item.list;
+        }
+      }
+    });
+  }
+
+
+  back() {
+    this.router.navigate(['../position'], {relativeTo: this.routeInfo, queryParams: {random: Math.random()}});
+  }
+
+  addPanel() {
+    this.router.navigate(['../panelEdit'], {
+      relativeTo: this.routeInfo,
+      queryParams: {random: Math.random(), panelId: '', positionId: this.dataModel.publicitypositionid}
+    });
+  }
+
+  showBigImage(id) {
+    try {
+      var items = [];
+      let url = this.webServerHost + "/appApi/home/showImg/" + id;
+      let img = this.getImageWidth(url) || {width: 500, height: 300};
+      items.push({
+        src: url,
+        w: img.width || 500,
+        h: img.height || 300
+      })
+
+      this.photoSwipe.open(items, {
+        index: 0,
+        tapToClose: true
+      }, "pswp" + (Math.random() * 100000).toFixed(0).toString());
+    } catch (e) {
+      this.alertModal.alert("图片查看异常:" + e);
+    }
+  }
+
+  getImageWidth(url) {
+    let obj = {width: 0, height: 0}
+    try {
+      var img = new Image();
+      img.src = url;
+      // 如果图片被缓存,则直接返回缓存数据
+      if (img.complete) {
+        obj.width = img.width;
+        obj.height = img.height;
+        return obj
+      } else {
+        img.onload = function () {
+          obj.width = img.width;
+          obj.height = img.height;
+          return obj
+        }
+      }
+    } catch (e) {
+      this.alertModal.alert("图片高宽获取异常:" + e);
+      return obj;
+    }
+  }
+
+}

+ 101 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/edit/edit.component.html

@@ -0,0 +1,101 @@
+<ion-header class="header-theme2">
+  <ion-toolbar>
+    <ion-label class="title-center">编辑阵地信息</ion-label>
+    <ion-buttons slot="start">
+      <ion-back-button icon="ios-back2" text="" mode="md"></ion-back-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content>
+  <form #dataForm="ngForm" class="form-table">
+    <ion-item detail mode="md">
+      <ion-label>所属党组织<span class="danger">*</span></ion-label>
+      <app-partyselect [(dzzdm)]="dataModel.partycode" [(dzzmc)]="dataModel.partyname"></app-partyselect>
+    </ion-item>
+    <ion-item mode="md">
+      <ion-label>阵地名称<span class="danger">*</span></ion-label>
+      <ion-input #positionname="ngModel" name="positionname" id="positionname" [(ngModel)]="dataModel.positionname"
+                 placeholder="请输入阵地名称" required></ion-input>
+    </ion-item>
+    <ion-item detail mode="md">
+      <ion-label>阵地类别<span class="danger">*</span></ion-label>
+      <ion-select #positiontype="ngModel" name="positiontype"
+                  id="positiontype"
+                  [(ngModel)]="dataModel.positiontype" okText="确定" cancelText="取消" placeholder="请选择"
+                  interface="action-sheet" required>
+        <ion-select-option *ngFor="let item of positionTypeList"
+                           [value]="item.dickey">{{item.dicvalue}}</ion-select-option>
+      </ion-select>
+    </ion-item>
+    <ion-item detail mode="md">
+      <ion-label>等级<span class="danger">*</span></ion-label>
+      <ion-select #positionlevel="ngModel" name="positionlevel"
+                  id="positionlevel"
+                  [(ngModel)]="dataModel.positionlevel" okText="确定" cancelText="取消" placeholder="请选择"
+                  interface="action-sheet" required>
+        <ion-select-option *ngFor="let item of positionLevelList"
+                           [value]="item.dickey">{{item.dicvalue}}</ion-select-option>
+      </ion-select>
+    </ion-item>
+    <ion-item mode="md">
+      <ion-label>建设时间<span class="danger">*</span></ion-label>
+      <ion-datetime #buildtime="ngModel" displayFormat="YYYY-MM-DD" pickerFormat="YYYY MM DD"
+                    name="buildtime"
+                    id="buildtime"
+                    cancelText="取消" doneText="选择" placeholder="请选择时间"
+                    [(ngModel)]="dataModel.buildtime"
+                    max="{{maxDate}}"
+                    required></ion-datetime>
+    </ion-item>
+    <ion-item mode="md">
+      <ion-label>编号</ion-label>
+      <ion-input #positioncode="ngModel" name="positioncode" id="positioncode" [(ngModel)]="dataModel.positioncode"
+                 placeholder="请输入编号"></ion-input>
+    </ion-item>
+    <ion-item mode="md">
+      <ion-label>位置</ion-label>
+      <ion-input #address="ngModel" name="address" id="address"
+                 [(ngModel)]="dataModel.address" placeholder="请输入位置"></ion-input>
+    </ion-item>
+    <ion-item mode="md">
+      <ion-label>尺寸</ion-label>
+      <ion-input #sizes="ngModel" name="sizes" id="sizes"
+                 [(ngModel)]="dataModel.sizes" placeholder="请输入尺寸"></ion-input>
+    </ion-item>
+    <ion-item mode="md">
+      <ion-label>责任人</ion-label>
+      <ion-input #headusername="ngModel" name="headusername" id="headusername" placeholder="请输入责任人"
+                 [(ngModel)]="dataModel.headusername"></ion-input>
+    </ion-item>
+    <ion-item mode="md">
+      <ion-label>阵地更新记录</ion-label>
+      <ion-icon slot="end" (click)="editPanel(null)" name="add-circle-outline" size="large" color="danger"></ion-icon>
+    </ion-item>
+    <ion-list>
+      <ion-item-sliding *ngFor="let item of panelList">
+        <ion-item (click)="editPanel(item)" detail>
+          <div class="item-img">
+            <app-bimage [(fileid)]="item.panelimg"></app-bimage>
+          </div>
+          <ion-label>
+            <h2>{{item.title}}</h2>
+            <p>{{item.paneltime | date:'yyyy-MM-dd'}}</p>
+          </ion-label>
+        </ion-item>
+
+        <ion-item-options side="end">
+          <ion-item-option (click)="delete(item.panelid)">删除</ion-item-option>
+        </ion-item-options>
+      </ion-item-sliding>
+    </ion-list>
+
+    <div class="footer-btn">
+      <ion-button slot="end" color="danger" mode="ios"
+                  (click)="save()" [disabled]="!dataForm.form.valid">
+        提交
+      </ion-button>
+    </div>
+  </form>
+</ion-content>
+<app-photo-swipe></app-photo-swipe>
+

+ 31 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/edit/edit.component.scss

@@ -0,0 +1,31 @@
+ion-content{
+  z-index: 11;
+}
+
+ion-select::part(icon) {
+  display: none;
+}
+
+app-partyselect{
+  width: 75%;
+}
+
+.detail-open::part(detail-icon){
+  transform: rotate(90deg);
+  transition: transform 0.2s ease-out;
+}
+
+.detail-close::part(detail-icon){
+  transform: rotate(0deg);
+  transition: transform 0.2s ease-out;
+}
+
+.item-img{
+  width: 80px;
+  height: 50px;
+  padding-right: 10px;
+}
+
+.item-detail{
+  margin: 0px !important;
+}

+ 208 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/edit/edit.component.ts

@@ -0,0 +1,208 @@
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {DatePipe} from "@angular/common";
+import {ActivatedRoute, Router} from "@angular/router";
+import {ConfigService, RequsetData} from "../../../../../service/config.service";
+import {UserService} from "../../../../../service/user.service";
+import {AlertController, LoadingController, ModalController} from "@ionic/angular";
+import * as moment from 'moment';
+import {PhotoSwipeComponent} from "../../../../../comm/modal/photo-swipe/photo-swipe.component";
+import {PositionApi} from "../../../../../api/propagandawork/position";
+import {AlertModal} from "../../../../../comm/modal/alert";
+import {DictionaryApi} from "../../../../../api/system/dictionary";
+import {PanelApi} from "../../../../../api/propagandawork/position/panel";
+import {EditComponent as PanelEditComponent} from "../panel/edit/edit.component";
+
+@Component({
+  selector: 'app-edit',
+  templateUrl: './edit.component.html',
+  styleUrls: ['./edit.component.scss'],
+})
+export class EditComponent implements OnInit {
+
+  @ViewChild(PhotoSwipeComponent)
+  photoSwipe: PhotoSwipeComponent;
+
+  op: number = 0;
+  dataModel: any = {};
+  positionTypeList: any = [];
+  positionLevelList: any = [];
+  positionStateList: any = [];
+  panelList: any = [];
+  detailOpen: boolean = false;
+  webServerHost: string = '';
+  maxDate: any = moment(new Date()).format("YYYY-MM-DD");
+  panelCycleList: any = [];
+
+  constructor(private datePipe: DatePipe, private router: Router, private routeInfo: ActivatedRoute, private configService: ConfigService, private userService: UserService, public alertController: AlertController,
+              public modalController: ModalController, public loadingController: LoadingController
+    , private positionApi: PositionApi, private alertModal: AlertModal, private dictionaryApi: DictionaryApi, private panelApi: PanelApi) {
+  }
+
+  ngOnInit() {
+    this.routeInfo.queryParams.subscribe(params => {
+      this.dataModel.id = params['id'];
+      this.op = parseInt(params['op']);
+      this.getDictionList();
+      this.getData();
+    });
+
+    this.configService.GetConfig().subscribe((config) => {
+      this.webServerHost = config.webServerHost;
+    });
+  }
+
+  getData() {
+    this.positionApi.getData(this.dataModel.id, this.userService.GetUser().DZZDM).subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.dataModel = data.item;
+        this.getPanelList();
+      }
+    });
+  }
+
+  getDictionList() {
+    this.dictionaryApi.getDictionaryList('positionType').subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.positionTypeList = data.item;
+      }
+    });
+    this.dictionaryApi.getDictionaryList('psiLevel').subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.positionLevelList = data.item;
+      }
+    });
+    this.dictionaryApi.getDictionaryList('positionState').subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.positionStateList = data.item;
+      }
+    });
+    this.dictionaryApi.getDictionaryList('panelCycle').subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.panelCycleList = data.item;
+      }
+    });
+  }
+
+  getPanelList() {
+    this.panelApi.getList({
+      pageIndex: 1, pageSize: 100, positionId: this.dataModel.publicitypositionid
+    }).subscribe((data: RequsetData) => {
+      if (data.success) {
+        data.item.list.forEach(e => {
+          this.panelList.push({
+            panelid: e.PANELID,
+            title: e.TITLE,
+            paneltime: e.PANELTIME,
+            panelimg: e.PANELIMG,
+            remark: e.REMARK
+          });
+        });
+      }
+    });
+  }
+
+  save() {
+    this.alertModal.loading("提交中...").then((loading) => {
+      this.positionApi.save(this.dataModel, this.panelList).subscribe((data: RequsetData) => {
+        loading.dismiss();
+        if (data.success) {
+          this.back();
+        }
+        this.alertModal.alert(data.msg);
+      }, () => {
+        loading.dismiss();
+      });
+    });
+  }
+
+  back() {
+    this.router.navigate(['../../position'], {relativeTo: this.routeInfo, queryParams: {random: Math.random()}});
+  }
+
+  editPanel(panel) {
+    this.panelModal(panel);
+  }
+
+  delete(id) {
+    /*this.alertModal.confirm("确认删除?", () => {
+      this.alertModal.loading("正在删除").then((loading) => {
+        this.positionApi.deletePlan(id).subscribe((fdata: RequsetData) => {
+          loading.dismiss();
+          if (fdata.success) {
+            this.getPanelList();
+          }
+          this.alertModal.alert(fdata.msg);
+        }, () => {
+          loading.dismiss();
+        });
+      });
+    });*/
+
+    this.panelList = this.panelList.filter(e => e.panelid != id);
+  }
+
+  async panelModal(panel) {
+    const modal = await this.modalController.create({
+      component: PanelEditComponent,
+      componentProps: {
+        panel: panel
+      }
+    });
+
+    await modal.present();
+
+    const {data} = await modal.onWillDismiss();
+    if (data.rtnData != null) {
+      let panel = this.panelList.filter(e => e.panelid === data.rtnData.panelid)[0];
+      if (panel == null) {
+        this.panelList.push(data.rtnData);
+      } else {
+        panel = data.rtnData;
+      }
+    }
+  }
+
+  showBigImage(id) {
+    try {
+      var items = [];
+      let url = this.webServerHost + "/appApi/home/showImg/" + id;
+      let img = this.getImageWidth(url) || {width: 500, height: 300};
+      items.push({
+        src: url,
+        w: img.width || 500,
+        h: img.height || 300
+      })
+
+      this.photoSwipe.open(items, {
+        index: 0,
+        tapToClose: true
+      }, "pswp" + (Math.random() * 100000).toFixed(0).toString());
+    } catch (e) {
+      this.alertModal.alert("图片查看异常:" + e);
+    }
+  }
+
+  getImageWidth(url) {
+    let obj = {width: 0, height: 0}
+    try {
+      var img = new Image();
+      img.src = url;
+      // 如果图片被缓存,则直接返回缓存数据
+      if (img.complete) {
+        obj.width = img.width;
+        obj.height = img.height;
+        return obj
+      } else {
+        img.onload = function () {
+          obj.width = img.width;
+          obj.height = img.height;
+          return obj
+        }
+      }
+    } catch (e) {
+      this.alertModal.alert("图片高宽获取异常:" + e);
+      return obj;
+    }
+  }
+
+}

+ 55 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/panel/detail/detail.component.html

@@ -0,0 +1,55 @@
+<ion-header class="header-theme2">
+  <ion-toolbar>
+    <ion-label class="title-center">阵地信息</ion-label>
+    <ion-buttons slot="start">
+      <ion-back-button icon="ios-back2" mode="md"></ion-back-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content>
+  <form class="form-table">
+    <ion-item>
+      <ion-label>阵地名称</ion-label>
+      <ion-text>{{positionModel.positionname}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>所属党组织</ion-label>
+      <ion-text>{{positionModel.partyname}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>宣传标语</ion-label>
+      <ion-text>{{dataModel.title}}</ion-text>
+    </ion-item>
+    <ion-item>
+      <ion-label>更新时间</ion-label>
+      <ion-text>{{dataModel.paneltime | date:'yyyy-MM-dd'}}</ion-text>
+    </ion-item>
+    <!--<ion-item>
+      <ion-label>更新周期</ion-label>
+      <ion-text *ngIf="panelCycleList.length>0">
+        {{(panelCycleList | myfilter:'dickey':dataModel.panelcycle)[0].dicvalue }}
+      </ion-text>
+    </ion-item>-->
+    <ion-item>
+      <ion-label>宣传备注</ion-label>
+      <ion-text>{{dataModel.remark}}</ion-text>
+    </ion-item>
+    <ion-item style="--inner-border-width: 0px 0px 0px 0px;">
+      <ion-label>图片</ion-label>
+    </ion-item>
+    <app-imglist [(imgOption)]="imgOption"></app-imglist>
+  </form>
+  <ion-item *ngIf="panelList.length>0" (click)="detailOpen=!detailOpen" class="item-detail" [ngClass]="detailOpen?'detail-open':'detail-close'" detail>
+    <div class="line-y"></div>
+    阵地更新记录
+  </ion-item>
+  <ion-list *ngIf="detailOpen">
+    <ion-item *ngFor="let item of panelList">
+      <img src="{{webServerHost}}/appApi/home/showImg/{{item.PANELIMG}}" class="item-img" onerror="this.src='assets/icon/nopic.png';this.classList.remove('item-img')"/>
+      <ion-label>
+        <h2>{{item.TITLE}}</h2>
+        <p>{{item.PARTYNAME}}</p>
+      </ion-label>
+    </ion-item>
+  </ion-list>
+</ion-content>

+ 34 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/panel/detail/detail.component.scss

@@ -0,0 +1,34 @@
+ion-content{
+  z-index: 11;
+}
+
+ion-item {
+  --inner-border-width: 0px 0px 1px 0px;
+  margin-right: 10px;
+}
+
+.detail-open::part(detail-icon){
+  transform: rotate(90deg);
+  transition: transform 0.2s ease-out;
+}
+
+.detail-close::part(detail-icon){
+  transform: rotate(0deg);
+  transition: transform 0.2s ease-out;
+}
+
+ion-item{
+  img{
+    margin-right: 10px;
+    border-radius: 8px;
+    width: 80px;
+    height: 50px;
+  }
+  .item-img{
+    object-fit: cover;
+  }
+}
+
+.item-detail{
+  margin: 0px !important;
+}

+ 103 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/panel/detail/detail.component.ts

@@ -0,0 +1,103 @@
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute, Router} from "@angular/router";
+import {ModalController, NavController} from "@ionic/angular";
+import {ConfigService, RequsetData} from "../../../../../../service/config.service";
+import {UserService} from "../../../../../../service/user.service";
+import {PanelApi} from "../../../../../../api/propagandawork/position/panel";
+import {AlertModal} from "../../../../../../comm/modal/alert";
+import {DictionaryApi} from "../../../../../../api/system/dictionary";
+import {PositionApi} from "../../../../../../api/propagandawork/position";
+
+@Component({
+  selector: 'app-detail',
+  templateUrl: './detail.component.html',
+  styleUrls: ['./detail.component.scss'],
+})
+export class DetailComponent implements OnInit {
+
+  panelCycleList: any = [];
+  dataModel: any = {};
+  positionModel: any = {};
+  imgOption: any = {
+    fileRefid: '',
+    fileName: '',
+    fileType: 4,
+    isMulti: false,
+    readonly: true
+  };
+  imgList: any = [];
+  panelList: any = [];
+  detailOpen: boolean = false;
+  webServerHost: string = '';
+  type: number = 0;
+
+  constructor(private router: Router, private routeInfo: ActivatedRoute, private configService: ConfigService, private userService: UserService, public modalController: ModalController, private navCtrl: NavController
+    , private panelApi: PanelApi, private alertModal: AlertModal, private dictionaryApi: DictionaryApi, private positionApi: PositionApi) {
+  }
+
+  ngOnInit() {
+    this.routeInfo.queryParams.subscribe(params => {
+      this.dataModel.publicitypositionid = params['positionId'];
+      this.dataModel.panelid = params['panelId'];
+      this.type = params['type'];
+      this.imgOption.fileRefid = this.dataModel.panelid;
+      if (this.dataModel.publicitypositionid) {
+        this.getPosition();
+        if (this.type != 2) {
+          this.getPanelList();
+        }
+      }
+      this.getDictionList();
+
+    });
+
+    this.configService.GetConfig().subscribe((config) => {
+      this.webServerHost = config.webServerHost;
+    });
+  }
+
+  getData() {
+    this.panelApi.getData(this.dataModel.panelid,
+      this.dataModel.publicitypositionid
+    ).subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.dataModel = data.item;
+
+        this.imgOption.fileRefid = this.dataModel.panelid;
+        this.imgOption.fileName = this.dataModel.title;
+      }
+    });
+  }
+
+  getPosition() {
+    this.positionApi.getData(this.dataModel.publicitypositionid, '').subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.positionModel = data.item;
+        this.getData();
+      }
+    });
+  }
+
+  getDictionList() {
+    this.dictionaryApi.getDictionaryList('panelCycle').subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.panelCycleList = data.item;
+      }
+    });
+  }
+
+  getPanelList() {
+    this.panelApi.getList({
+      pageIndex: 1, pageSize: 100, positionId: this.dataModel.publicitypositionid
+    }).subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.panelList = data.item.list.filter(it => it.PANELID != this.dataModel.panelid);
+      }
+    });
+  }
+
+  back() {
+    this.router.navigate(['../panel'], {relativeTo: this.routeInfo});
+  }
+
+}

+ 43 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/panel/edit/edit.component.html

@@ -0,0 +1,43 @@
+<ion-header class="header-theme2">
+  <ion-toolbar>
+    <ion-label class="title-center">编辑阵地图片信息</ion-label>
+    <ion-buttons slot="start">
+      <ion-back-button icon="ios-back2" mode="md"></ion-back-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content>
+  <form #dataForm="ngForm" class="form-table">
+    <ion-item mode="md">
+      <ion-label>宣传标语</ion-label>
+      <ion-input #title="ngModel" readonly="false" placeholder="请填写主题" name="title"
+                 [(ngModel)]="dataModel.title" required></ion-input>
+    </ion-item>
+    <ion-item detail mode="md">
+      <ion-label>更新时间</ion-label>
+      <ion-datetime #paneltime="ngModel" displayFormat="YYYY-MM-DD" pickerFormat="YYYY MM DD"
+                    name="paneltime"
+                    id="paneltime"
+                    cancelText="取消" doneText="选择" placeholder="请输入时间"
+                    [(ngModel)]="dataModel.paneltime"
+                    max="{{maxDate}}"
+                    required></ion-datetime>
+    </ion-item>
+    <ion-item mode="md">
+      <ion-label>宣传备注</ion-label>
+      <ion-textarea readonly="false" placeholder="请填写宣传备注" name="remark"
+                    [(ngModel)]="dataModel.remark"></ion-textarea>
+    </ion-item>
+    <ion-item mode="md">
+      <ion-label>上传图片</ion-label>
+    </ion-item>
+    <app-imglist [(imgOption)]="imgOption" [(imgList)]="imgList"></app-imglist>
+    <ion-label  style="color: red;">备注:以上可上传照片,此项为选传项,仅作资料留存,不作为必传项点,也不得作为检查、考核项点。</ion-label>
+    <div class="footer-btn">
+      <ion-button color="light" (click)="back()" mode="ios">关闭</ion-button>
+      <ion-button slot="end" color="danger" mode="ios" (click)="save()"
+                  [disabled]="!dataForm.form.valid">保存
+      </ion-button>
+    </div>
+  </form>
+</ion-content>

+ 38 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/panel/edit/edit.component.scss

@@ -0,0 +1,38 @@
+ion-content{
+  z-index: 11;
+}
+
+ion-select::part(icon) {
+  display: none;
+}
+
+app-partyselect{
+  width: 75%;
+}
+
+.detail-open::part(detail-icon){
+  transform: rotate(90deg);
+  transition: transform 0.2s ease-out;
+}
+
+.detail-close::part(detail-icon){
+  transform: rotate(0deg);
+  transition: transform 0.2s ease-out;
+}
+
+ion-item{
+  img{
+    margin-right: 10px;
+    border-radius: 8px;
+    width: 80px;
+    height: 50px;
+  }
+  .item-img{
+    object-fit: cover;
+  }
+}
+
+.item-detail{
+  margin: 0px !important;
+}
+

+ 52 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/panel/edit/edit.component.ts

@@ -0,0 +1,52 @@
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute, Router} from "@angular/router";
+import {ModalController, NavParams} from "@ionic/angular";
+import * as moment from 'moment';
+import * as uuid from 'uuid';
+
+@Component({
+  selector: 'app-edit',
+  templateUrl: './edit.component.html',
+  styleUrls: ['./edit.component.scss'],
+})
+export class EditComponent implements OnInit {
+
+  dataModel: any = {};
+  imgOption: any = {
+    fileRefid: '',
+    fileName: '',
+    fileType: 4,
+    isMulti: true,
+    readonly: false
+  };
+  imgList = [];
+  panelList: any = [];
+  webServerHost: string = '';
+  maxDate: any = moment(new Date()).format("YYYY-MM-DD");
+
+  constructor(private router: Router, private routeInfo: ActivatedRoute,  public modalController: ModalController,navParams: NavParams) {
+    this.dataModel = navParams.get('panel') || {panelid:uuid.v4()};
+    this.imgOption.fileRefid = this.dataModel.panelid;
+  }
+
+  ngOnInit() {
+
+  }
+
+  save() {
+    if (this.imgList.length > 0) {
+      this.dataModel.panelimg = this.imgList[0].fileid;
+    }
+
+    this.modalController.dismiss({
+      'dismissed': true,
+      'rtnData': this.dataModel
+    });
+  }
+
+  back() {
+    this.modalController.dismiss({
+      'dismissed': true
+    });
+  }
+}

+ 52 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/position.component.html

@@ -0,0 +1,52 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-label>阵地管理</ion-label>
+    <ion-buttons slot="start">
+      <ion-back-button icon="ios-back" mode="md"></ion-back-button>
+    </ion-buttons>
+    <ion-searchbar slot="end" mode="ios" enterkeyhint="search" placeholder="搜索阵地名称" showCancelButton="never"
+                   (ionChange)="searchChange($event)"></ion-searchbar>
+  </ion-toolbar>
+  <app-partysearch [(dzzdm)]="searchParams.dzzdm" (dzzdmChange)="reload()"></app-partysearch>
+  <ion-item class="item-filter">
+    <div slot="end" (click)="search()">
+      <span>条件筛选</span>
+      <ion-icon name="dj-search"></ion-icon>
+    </div>
+  </ion-item>
+</ion-header>
+<ion-content>
+  <ion-list>
+    <ion-item-sliding *ngFor="let item of dataList">
+      <ion-item detail [routerLink]="['./edit']" [queryParams]="{id: item.PUBLICITYPOSITIONID,op:1,panelid:item.PANELID}">
+        <div class="item-img">
+          <app-bimage [(fileid)]="item.PANELIMG"></app-bimage>
+        </div>
+        <ion-label>
+          <h2>{{item.POSITIONNAME}}<span class="dues-month">{{item.PANELTIME!=null?(item.PANELTIME | date:'yyyy-MM-dd'):'无更新记录'}}</span></h2>
+          <p>{{item.PARTYNAME}}</p>
+        </ion-label>
+      </ion-item>
+
+      <ion-item-options side="end">
+        <ion-item-option (click)="delete(item.PUBLICITYPOSITIONID)">删除</ion-item-option>
+      </ion-item-options>
+    </ion-item-sliding>
+  </ion-list>
+  <ion-infinite-scroll threshold="100px" (ionInfinite)="scroll($event)">
+    <ion-infinite-scroll-content
+      loadingSpinner="bubbles"
+      loadingText="{{total>searchParams.pageIndex*searchParams.pageSize?'正在加载...':'暂无更多'}}">
+    </ion-infinite-scroll-content>
+  </ion-infinite-scroll>
+  <ion-fab vertical="bottom" horizontal="center" slot="fixed" class="fab-add">
+    <ion-fab-button>
+      <ion-text class="btn-add" (click)="add()">
+        <img src="assets/icon/btnadd.png" style="width: 30px;height:30px;">
+        <span class="btn-add-text">新增</span>
+      </ion-text>
+    </ion-fab-button>
+  </ion-fab>
+</ion-content>
+
+

+ 42 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/position.component.scss

@@ -0,0 +1,42 @@
+ion-label {
+  margin: 3px !important;
+  padding: 0px;
+  white-space: normal !important;
+}
+.dues-month{
+  color: #998989;
+  font-size: 12px;
+  border-radius: 4px;
+  background-color: #F3F3F3;
+  padding: 0px 4px;
+  margin-left: 20px;
+}
+
+.dues-money{
+  color: #DE4F3F;
+}
+
+ion-select {
+  color: #5E4545;
+
+  --placeholder-color: #5E4545;
+
+  --placeholder-opacity: 1;
+}
+ion-select::part(icon) {
+  color: #5E4545;
+  opacity: 1;
+}
+ion-header {
+  ion-item {
+    --inner-border-width:  0px;
+    --border-width:0px;
+  }
+}
+
+.item-img{
+  width: 80px;
+  height: 50px;
+  padding-right: 10px;
+}
+

+ 171 - 0
parth5/parth5/src/app/views/pages/propagandawork/position/position.component.ts

@@ -0,0 +1,171 @@
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {AlertController, IonInfiniteScroll, LoadingController, ModalController, NavController} from "@ionic/angular";
+import {ActivatedRoute, Router} from "@angular/router";
+import {ConfigService, RequsetData} from "../../../../service/config.service";
+import {UserService} from "../../../../service/user.service";
+import {SearchComponent} from "../../../../comm/modal/search/search.component";
+import {PositionApi, reqParams} from "../../../../api/propagandawork/position";
+import {AlertModal} from "../../../../comm/modal/alert";
+
+@Component({
+  selector: 'app-position',
+  templateUrl: './position.component.html',
+  styleUrls: ['./position.component.scss'],
+})
+export class PositionComponent implements OnInit {
+
+  @ViewChild(IonInfiniteScroll, {static: true}) infiniteScroll: IonInfiniteScroll;
+
+  webServerHost: string = '';
+  userInfo: any = {};
+  dataList: any[] = [];
+  searchParams: reqParams = {
+    pageIndex: 1,
+    pageSize: 15,
+    dzzdm: '',
+    positionName: '',
+    positionType: null,
+    positionLevel: null,
+    positionState: null,
+    startDate: '',
+    endDate: ''
+  };
+  total: number = 15;
+  fieldList: any[] = [{label: '阵地名称', name: 'positionName', type: 'text', value: '', placeholder: '输入阵地名称'},
+    {
+      label: '建设日期',
+      name: '',
+      type: 'group-datetime',
+      inputs: [{name: 'startDate', type: 'datetime', value: '', placeholder: '开始日期'}, {
+        name: 'endDate',
+        type: 'datetime',
+        value: '',
+        placeholder: '结束日期'
+      }]
+    },
+    {
+      label: '阵地类别',
+      name: 'positionType',
+      type: 'select',
+      value: '',
+      dicParams: {
+        getUrl: 'getDictionaryListByDicTypeKey',
+        dicTypeKey: 'positionType',
+        textField: 'dicvalue',
+        valueField: 'dickey',
+        ismulti: true
+      }
+    },
+    {
+      label: '等级',
+      name: 'positionLevel',
+      type: 'select',
+      value: '',
+      dicParams: {
+        getUrl: 'getDictionaryListByDicTypeKey',
+        dicTypeKey: 'psiLevel',
+        textField: 'dicvalue',
+        valueField: 'dickey',
+        ismulti: true
+      }
+    }
+  ];
+
+  constructor(private router: Router, private routeInfo: ActivatedRoute, private configService: ConfigService, private userService: UserService, public modalController: ModalController, private navCtrl: NavController
+    , private positionApi: PositionApi, private alertModal: AlertModal) {
+  }
+
+  ngOnInit() {
+    this.userInfo = this.userService.GetUser();
+    this.routeInfo.queryParams.subscribe(params => {
+      this.searchParams.dzzdm = this.searchParams.dzzdm || this.userService.GetUser().dataDzzdm;
+      this.reload();
+    });
+    this.configService.GetConfig().subscribe((config) => {
+      this.webServerHost = config.webServerHost;
+    });
+  }
+
+  getList() {
+    this.positionApi.getList(this.searchParams).subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.dataList = this.dataList.concat(data.item.list);
+        this.total = data.item.total;
+      }
+    });
+  }
+
+  reload() {
+    this.dataList = [];
+    this.searchParams.pageIndex = 1;
+    this.total = 15;
+    this.getList();
+  }
+
+  scroll(event) {
+    setTimeout(() => {
+      event.target.complete();
+      if (this.total > this.searchParams.pageIndex * this.searchParams.pageSize) {
+        this.searchParams.pageIndex += 1;
+        this.getList();
+      }
+    }, 500);
+  }
+
+  yearChange(e) {
+    this.reload();
+  }
+
+  searchChange(event) {
+    this.fieldList[0].value = event.detail.value;
+    this.searchParams.positionName = event.detail.value;
+    this.reload();
+  }
+
+  async search() {
+    const modal = await this.modalController.create({
+      component: SearchComponent,
+      componentProps: {
+        'fieldList': this.fieldList
+      },
+      cssClass: 'search-modal'
+    });
+
+    await modal.present();
+
+    const {data} = await modal.onWillDismiss();
+    if (data && data.success) {
+      this.searchParams.positionName = data.params.positionName;
+      this.searchParams.startDate = data.params.startDate;
+      this.searchParams.endDate = data.params.endDate;
+      this.searchParams.positionType = data.params.positionType;
+      this.searchParams.positionLevel = data.params.positionLevel;
+      this.reload();
+    }
+  }
+
+  add() {
+    this.router.navigate(['./edit'], {
+      relativeTo: this.routeInfo,
+      queryParams: {random: Math.random(), op: 0}
+    });
+  }
+
+
+  delete(id) {
+    this.alertModal.confirm("确认删除?", () => {
+      this.alertModal.loading("正在删除").then((loading) => {
+        this.positionApi.delete(id).subscribe((fdata: RequsetData) => {
+          loading.dismiss();
+          if (fdata.success) {
+            this.reload();
+          }
+          this.alertModal.alert(fdata.msg);
+        }, () => {
+          loading.dismiss();
+        });
+      });
+    });
+  }
+
+}

+ 3 - 1
parth5/parth5/src/app/views/tapp/tab-main/tab-main.module.ts

@@ -15,6 +15,7 @@ import {PhotoshowComponent} from "../../../comm/modal/photoshow/photoshow.compon
 import {PhotoSwipeComponent} from "../../../comm/modal/photo-swipe/photo-swipe.component";
 import {MyfilterPipe} from "../../../comm/pipes/myfilter.pipe";
 import {SelectuserComponent} from "../../pages/partyuser/party-dues/selectuser/selectuser.component";
+import {BimageComponent} from "../../../comm/modal/bimage/bimage.component";
 
 const pubComponents = [
   PartysearchComponent,
@@ -26,7 +27,8 @@ const pubComponents = [
   PhotoshowComponent,
   PhotoSwipeComponent,
   MyfilterPipe,
-  SelectuserComponent
+  SelectuserComponent,
+  BimageComponent
 ];
 
 /*function getRoutesComponent(routes: Routes) {

+ 3 - 1
parth5/parth5/src/app/views/tapp/tab-main/tab-main.route.ts

@@ -4,6 +4,7 @@ import partyInfoRoutes from "../../../routes/partyInfo";
 import partyUserRoutes from "../../../routes/partyUser";
 import shykRoutes from "../../../routes/shyk";
 import partyDuesRoutes from "../../../routes/partyDues";
+import positionRoutes from "../../../routes/propagandawork/position";
 
 export const routes: Routes = [
   {
@@ -13,5 +14,6 @@ export const routes: Routes = [
   ...partyInfoRoutes,
   ...partyUserRoutes,
   ...shykRoutes,
-  ...partyDuesRoutes
+  ...partyDuesRoutes,
+  ...positionRoutes
 ];

+ 5 - 1
src/main/java/com/ghsc/partybuild/controller/app/AppPublicityController.java

@@ -3,6 +3,7 @@ package com.ghsc.partybuild.controller.app;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ghsc.partybuild.vo.shyk.MeetingTopicJsonData;
 import com.github.pagehelper.PageInfo;
 import com.ghsc.partybuild.controller.jsonmodel.RequsetData;
 import com.ghsc.partybuild.model.*;
@@ -247,7 +248,10 @@ public class AppPublicityController {
             String userId = reqMap.get("userId").toString();
             String userName = reqMap.get("userName").toString();
 
-            count = publicityService.savePublicityPosition(dataModel, userId, userName);
+            List<PubPublicitypositionPanel> panelList = JsonMapper.jsonToObject(reqMap.get("panelList").toString(), new TypeReference<List<PubPublicitypositionPanel>>() {
+            });
+
+            count = publicityService.savePublicityPositionAndPanel(dataModel,panelList, userId, userName);
 
         } catch (Exception e) {
 

+ 2 - 0
src/main/java/com/ghsc/partybuild/service/PublicityService.java

@@ -53,6 +53,8 @@ public interface PublicityService {
      */
     int savePublicityPosition(PubPublicityposition model, String userId, String userName);
 
+    int savePublicityPositionAndPanel(PubPublicityposition model,List<PubPublicitypositionPanel> panelList, String userId, String userName);
+
     /**
      * 删除宣传阵地信息
      * @param id

+ 80 - 1
src/main/java/com/ghsc/partybuild/service/impl/PublicityServiceImpl.java

@@ -175,6 +175,85 @@ public class PublicityServiceImpl implements PublicityService {
         return result;
     }
 
+    /**
+     * @param model
+     * @param userId
+     * @param userName
+     * @return
+     */
+    @Override
+    public int savePublicityPositionAndPanel(PubPublicityposition model, List<PubPublicitypositionPanel> panelList, String userId, String userName) {
+        int result = 0;
+        PubPublicityposition dbModel = getPublicityPositionById(model.getPublicitypositionid());
+        if (dbModel == null || (model != null && stringUtils.IsNullOrEmpty(model.getPublicitypositionid()))) {
+            model.setCreatetime(new Date());
+            model.setCreateuserid(userId);
+            model.setCreateusername(userName);
+            model.setOperatestate("A");
+            model.setOperatetime(new Date());
+            model.setSyncstate("N");
+
+            result = pubPublicitypositionMapper.insert(model);
+        } else {
+
+            model.setUpdatetime(new Date());
+            model.setUpdateuserid(userId);
+            model.setUpdateusername(userName);
+            model.setOperatestate("M");
+            model.setOperatetime(new Date());
+            model.setSyncstate("N");
+
+            result = pubPublicitypositionMapper.updateByPrimaryKey(model);
+        }
+
+        PubPublicitypositionPanelExample exp = new PubPublicitypositionPanelExample();
+        PubPublicitypositionPanelExample.Criteria cri = exp.or();
+        cri.andPublicitypositionidEqualTo(model.getPublicitypositionid());
+        List<PubPublicitypositionPanel> dbPanelList = pubPublicitypositionPanelMapper.selectByExample(exp);
+        List<String> dbPanelIdList = dbPanelList.stream().map(PubPublicitypositionPanel::getPanelid).collect(Collectors.toList());
+        List<String> newPanelIdList = panelList.stream().map(PubPublicitypositionPanel::getPanelid).collect(Collectors.toList());
+        List<String> removePanelIdList = dbPanelIdList.stream().filter(e -> !newPanelIdList.contains(e)).collect(Collectors.toList());
+
+        if (removePanelIdList.size() > 0) {
+            cri.andPanelidIn(removePanelIdList);
+
+            pubPublicitypositionPanelMapper.deleteByExample(exp);
+        }
+
+
+        panelList.forEach(panel -> {
+            PubPublicitypositionPanel dbPanel = dbPanelList.stream().filter(it -> it.getPanelid().equals(panel.getPanelid())).findFirst().orElse(null);
+            if (dbPanel == null) {
+                panel.setPublicitypositionid(model.getPublicitypositionid());
+                panel.setCreatetime(new Date());
+                panel.setCreateuserid(userId);
+                panel.setCreateusername(userName);
+                panel.setOperatestate("A");
+                panel.setOperatetime(new Date());
+                panel.setSyncstate("N");
+                panel.setPanelstate(0);
+
+                pubPublicitypositionPanelMapper.insert(panel);
+            } else {
+                dbPanel.setTitle(panel.getTitle());
+                dbPanel.setRemark(panel.getRemark());
+                dbPanel.setPaneltime(panel.getPaneltime());
+                dbPanel.setPanelcycle(panel.getPanelcycle());
+                dbPanel.setPanelimg(panel.getPanelimg());
+                dbPanel.setUpdatetime(new Date());
+                dbPanel.setUpdateuserid(userId);
+                dbPanel.setUpdateusername(userName);
+                dbPanel.setOperatestate("M");
+                dbPanel.setOperatetime(new Date());
+                dbPanel.setSyncstate("N");
+
+                pubPublicitypositionPanelMapper.updateByPrimaryKey(dbPanel);
+            }
+        });
+
+        return result;
+    }
+
     /**
      * @param id
      * @return
@@ -1258,7 +1337,7 @@ public class PublicityServiceImpl implements PublicityService {
     }
 
     @Override
-    public int deleteDuesById(String id,String userId) {
+    public int deleteDuesById(String id, String userId) {
         UsPartyduesDetail detail = usPartyduesDetailMapper.selectByPrimaryKey(id);
         detail.setMoney(null);
         detail.setPaystate(0);

+ 2 - 1
src/main/resources/mapping/PublicityCQuery.xml

@@ -60,7 +60,7 @@
         <if test="zzfbType != null">
             and SUBSTR(p.partyCode,1,12) in(select dzzdm from ZZ_DZZFBQK where zzfb= #{zzfbType})
         </if>
-        order by IF(ISNULL(panel.PANELTIME),1,0) desc,p.PARTYCODE,p.CREATETIME desc
+        order by panel.PANELTIME desc,p.PARTYCODE,p.CREATETIME desc
     </select>
 
     <select id="selectPublicityPanelList" resultType="java.util.HashMap">
@@ -140,6 +140,7 @@
     <select id="selectPublicityPanelRecordList" resultType="java.util.HashMap">
         select p.PUBLICITYPOSITIONID,p.POSITIONNAME,panel.TITLE,panel.PANELIMG,panel.CREATEUSERNAME,panel.PANELTIME,
         panel.PANELCYCLE,panel.PANELSTATE,panel.PANELID,z.DZZMC as PARTYNAME
+        ,panel.REMARK
         from PUB_PUBLICITYPOSITION p
         inner join PUB_PUBLICITYPOSITION_PANEL panel on p.PUBLICITYPOSITIONID=panel.PUBLICITYPOSITIONID
         inner join ZZ_ZZQKXX z on p.partycode=z.dzzdm