Parcourir la source

Merge remote-tracking branch 'origin/master'

yusm il y a 3 semaines
Parent
commit
aae28438eb

+ 22 - 0
fhKeeper/formulahousekeeper/course-pc/src/routes.js

@@ -14,6 +14,8 @@ import examCertification from './views/examCertification/examCertification.vue'
 import gcpCertification from './views/gcpCertification/gcpCertification.vue'
 import offlineRegistration from './views/offlineRegistration/registration.vue'
 import hotTopicCarousel from './views/hotTopicCarousel/hotTopicCarousel.vue'
+import myMessage from './views/myMessage/myMessage.vue'
+import customerServiceCenter from './views/customerServiceCenter/customerServiceCenter.vue'
 
 Vue.use(Router)
 
@@ -112,6 +114,26 @@ export const allRouters = [
             { path: '/gcpc-certification', component: gcpCertification, name: 'GCP证书展示' }
         ]
     },
+    {
+        path: '/my-message',
+        component: Home,
+        name: '我的消息',
+        iconCls: 'iconfont firerock-iconkehu',
+        leaf: true,
+        children: [
+            { path: '/my-message', component: myMessage, name: '我的消息' }
+        ]
+    },
+    {
+        path: '/customer-service-center',
+        component: Home,
+        name: '客服中心',
+        iconCls: 'iconfont firerock-iconkehu',
+        leaf: true,
+        children: [
+            { path: '/customer-service-center', component: customerServiceCenter, name: '客服中心' }
+        ]
+    },
     {
         path: '*',
         hidden: true,

+ 233 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/customerServiceCenter/customerServiceCenter.vue

@@ -0,0 +1,233 @@
+<template>
+  <div class="gcp-certification">
+    <h2 class="title">客服中心上传</h2>
+    <div class="upload-height">
+      <div class="upload-area">
+        <!-- 上传按钮 -->
+        <div class="imageUpload">
+          <el-upload ref="pictureCardRef" action="#" list-type="picture-card" :multiple="false"
+            :show-file-list="false" :http-request="uploadKFZXImg" accept="image/*" :disabled="fileList.length > 0">
+            <i class="el-icon-plus"></i>
+          </el-upload>
+        </div>
+        <!-- 视频或图片 -->
+        <div class="image-list">
+          <div v-for="(file, index) in fileList" :key="index" :class="`${!file.loading ? 'image-item-hover' : ''} image-item`">
+            <img :src="file.url" class="cert-image" @click="previewImage(index)">
+            <div class="image-actions" v-if="!file.loading">
+              <el-button type="danger" icon="el-icon-delete" circle @click.stop="removeImage(index)"></el-button>
+              <el-button type="primary" icon="el-icon-view" circle @click.stop="previewImage(index)"></el-button>
+            </div>
+            <div class="image-actions-loging" v-if="file.loading">
+              文件上传中...
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Vue from 'vue'
+import Viewer from 'v-viewer'
+import 'viewerjs/dist/viewer.css'
+
+Vue.use(Viewer)
+
+import { post, checkAndAddUpload } from '../../api'
+export default {
+  name: 'GcpCertification',
+  data() {
+    return {
+      fileList: [],
+      imageList: [],
+      imageListTime: null,
+    }
+  },
+  methods: {
+    uploadKFZXImg(file) {
+      this.imageList.unshift(file.file)
+      if (this.imageListTime) {
+        clearTimeout(this.imageListTime)
+      }
+      this.imageListTime = setTimeout(() => {
+        this.batchUploadGCPimg()
+      }, 500)
+    },
+    batchUploadGCPimg() {
+      for (let i = 0; i < this.imageList.length; i++) {
+        const formData = new FormData()
+        formData.append('coverImage', this.imageList[i])
+        this.fileList.unshift({
+          name: 'a',
+          loading: true,
+          url: '',
+          imgError: ''
+        })
+        this.http.uploadFile(`/customer-qr/uploadAndSave`, formData, res => {
+          this.fileList[i].url = checkAndAddUpload(res.data.coverUrl)
+          this.fileList[i].name = res.data.id
+          this.fileList[i].loading = false
+        }, err => {
+          this.fileList[i].loading = false
+          this.fileList[i].imgError = '图片上传失败'
+        })
+      }
+
+      setTimeout(() => {
+        this.imageList = []
+        this.$refs.pictureCardRef.clearFiles()
+      }, 1500)
+    },
+    removeImage(index) {
+      this.$confirm('此操作将永久删除该图片, 是否继续?', '删除图片', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        post(`/customer-qr/delete`, { id: this.fileList[index].name }).then(res => {
+          this.$message({
+            type: 'success',
+            message: '删除成功!'
+          })
+          this.fileList.splice(index, 1)
+        })
+      })
+    },
+    previewImage(index) {
+      this.$viewerApi({
+        images: this.fileList.map(f => f.url),
+        options: {
+          initialViewIndex: index,
+          toolbar: {
+            zoomIn: 1,
+            zoomOut: 1,
+            oneToOne: 1,
+            reset: 1,
+            prev: 1,
+            next: 1,
+            rotateLeft: 1,
+            rotateRight: 1,
+            flipHorizontal: 1,
+            flipVertical: 1
+          }
+        }
+      })
+    },
+    obtainCertificateList() {
+      post(`/customer-qr/getOne`, {}).then(res => {
+        this.fileList = [res.data].map(item => {
+          return {
+            name: item.id,
+            url: checkAndAddUpload(item.coverUrl),
+            loading: false,
+            imgError: ''
+          }
+        }).reverse()
+      })
+    }
+  },
+  mounted() {
+    this.obtainCertificateList()
+  }
+}
+</script>
+
+<style scoped>
+.gcp-certification {
+  max-width: 1200px;
+  margin: 0 auto;
+  padding: 20px;
+}
+
+.title {
+  text-align: center;
+  margin-bottom: 30px;
+  color: #333;
+}
+
+.upload-area {
+  display: flex;
+  flex-wrap: wrap;
+  margin-bottom: 30px;
+}
+
+.upload-height {
+  height: 70vh;
+  overflow-y: auto;
+}
+
+.hide-upload>>>.el-upload--picture-card {
+  display: none;
+}
+
+.image-list {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 20px;
+  margin-bottom: 30px;
+}
+
+.imageUpload {
+  margin-right: 20px;
+}
+
+.image-item {
+  position: relative;
+  width: 148px;
+  height: 148px;
+  border-radius: 4px;
+  overflow: hidden;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  transition: all 0.3s;
+}
+
+.image-item:hover {
+  transform: translateY(-5px);
+  box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.2);
+}
+
+.image-item-hover:hover .image-actions {
+  opacity: 1;
+}
+
+.cert-image {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  cursor: pointer;
+}
+
+.image-actions {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: rgba(0, 0, 0, .5);
+  gap: 10px;
+  opacity: 0;
+  transition: opacity 0.3s;
+}
+
+.image-actions-loging {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: rgba(0, 0, 0, .5);
+  color: #fff;
+}
+
+.submit-area {
+  text-align: center;
+}
+</style>

+ 249 - 0
fhKeeper/formulahousekeeper/course-pc/src/views/myMessage/myMessage.vue

@@ -0,0 +1,249 @@
+<template>
+    <section>
+        <!--工具条-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true" @submit.native.prevent>
+                <el-form-item>
+                    <el-input v-model.trim="messageContent" placeholder="请输入消息内容" clearable size="small" style="width: 80vw"></el-input>
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" @click="sendMessage" size="small" :disabled="!messageContent.length">发送消息</el-button>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <!--列表-->
+        <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;" @selection-change="handleSelectionChange">
+            <el-table-column type="selection" width="55" align="center"></el-table-column>
+            <el-table-column prop="content" label="历史消息" min-width="300" align="center"></el-table-column>
+            <el-table-column prop="createTime" label="时间" width="180" align="center"></el-table-column>
+            <el-table-column label="操作" width="240" class-name="btns" header-align="center" fixed="right">
+                <template slot-scope="scope">
+                    <el-button v-if="scope.row.status == 1" size="small">已发送</el-button>
+                    <el-button v-if="scope.row.status == 0" size="small" type="success" @click="resendMessage(scope.row)">发送</el-button>
+                    <el-button v-if="scope.row.status == 0" size="small" type="primary" @click="showEditDialog(scope.row)">编辑</el-button>
+                    <el-button size="small" type="danger" @click="deleteMessage(scope.row)">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <!--工具条-->
+        <el-col :span="24" class="toolbar">
+            <el-button type="danger" @click="batchDelete" :disabled="selectedIds.length===0" size="small">批量删除</el-button>
+            <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :page-sizes="[10, 20, 50, 100]"
+                :page-size="size"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="total"
+                style="float:right;"
+            ></el-pagination>
+        </el-col>
+        <!--编辑弹窗-->
+        <el-dialog title="编辑消息" :visible.sync="editDialogVisible" width="50%">
+            <el-form :model="editForm" label-width="80px">
+                <el-form-item label="消息内容">
+                    <el-input type="textarea" v-model="editForm.content" :rows="5"></el-input>
+                </el-form-item>
+            </el-form>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="editDialogVisible = false">取 消</el-button>
+                <el-button type="primary" @click="saveEdit">确 定</el-button>
+            </span>
+        </el-dialog>
+    </section>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            // 消息内容
+            messageContent: '',
+
+            // 表格相关
+            tableHeight: 0,
+            listLoading: false,
+            total: 0,
+            page: 1,
+            size: 20,
+            list: [],
+            selectedIds: [],
+
+            // 编辑相关
+            editDialogVisible: false,
+            editForm: {
+                id: '',
+                content: ''
+            },
+        }
+    },
+    methods: {
+        // 显示编辑弹窗
+        showEditDialog(row) {
+            this.editForm = {
+                id: row.id,
+                content: row.content
+            };
+            this.editDialogVisible = true;
+        },
+
+        // 发送/更新消息
+        sendMessage() {
+            if (!this.messageContent) {
+                this.$message.warning('请输入消息内容');
+                return;
+            }
+
+            this.listLoading = true;
+            this.http.post('/information-manage/saveOrUpdate', {
+                content: this.messageContent
+            }, res => {
+                if (res.code === 'ok') {
+                    this.$message.success('发送成功');
+                    this.messageContent = '';
+                    this.getList();
+                } else {
+                    this.$message.error(res.msg || '发送失败');
+                }
+                this.listLoading = false;
+            }, () => {
+                this.listLoading = false;
+            })
+        },
+
+        // 保存编辑
+        saveEdit() {
+            this.listLoading = true;
+            this.http.post('/information-manage/saveOrUpdate', this.editForm, res => {
+                if (res.code === 'ok') {
+                    this.$message.success('修改成功');
+                    this.editDialogVisible = false;
+                    this.getList();
+                } else {
+                    this.$message.error(res.msg || '修改失败');
+                }
+                this.listLoading = false;
+            }, () => {
+                this.listLoading = false;
+            })
+        },
+
+        // 重新发送消息
+        resendMessage(row) {
+            this.$confirm('确认发送该消息?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                this.http.post('/information-manage/sendMsgByManager', { id: row.id }, res => {
+                    if (res.code === 'ok') {
+                        this.$message.success('发送成功');
+                        this.getList()
+                    } else {
+                        this.$message.error(res.msg || '发送失败');
+                    }
+                })
+            })
+        },
+
+        // 获取消息列表
+        getList() {
+            this.listLoading = true;
+            this.http.post('/information-manage/pageList', {
+                page: this.page,
+                size: this.size
+            }, res => {
+                this.list = res.data.records;
+                this.total = res.data.total;
+                this.listLoading = false;
+            }, () => {
+                this.listLoading = false;
+            })
+        },
+
+        // 分页相关
+        handleCurrentChange(val) {
+            this.page = val;
+            this.getList();
+        },
+        handleSizeChange(val) {
+            this.page = 1;
+            this.size = val;
+            this.getList();
+        },
+
+        // 选择变化
+        handleSelectionChange(val) {
+            this.selectedIds = val.map(item => item.id);
+        },
+
+        // 删除消息
+        deleteMessage(row) {
+            this.$confirm('确认删除该消息?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                this.http.post('/information-manage/delete', { ids: row.id }, res => {
+                    if (res.code === 'ok') {
+                        this.$message.success('删除成功');
+                        this.getList();
+                    } else {
+                        this.$message.error(res.msg || '删除失败');
+                    }
+                })
+            })
+        },
+
+        // 批量删除
+        batchDelete() {
+            if (this.selectedIds.length === 0) {
+                this.$message.warning('请选择要删除的消息');
+                return;
+            }
+
+            this.$confirm(`确认删除选中的${this.selectedIds.length}条消息?`, '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                this.http.post('/information-manage/delete', { ids: this.selectedIds.join(',') }, res => {
+                    if (res.code === 'ok') {
+                        this.$message.success('批量删除成功');
+                        this.getList();
+                        this.selectedIds = [];
+                    } else {
+                        this.$message.error(res.msg || '删除失败');
+                    }
+                })
+            })
+        }
+    },
+
+    created() {
+        let height = window.innerHeight;
+        this.tableHeight = height - 195;
+        const that = this;
+        window.onresize = function temp() {
+            that.tableHeight = window.innerHeight - 195;
+        };
+    },
+
+    mounted() {
+        this.getList();
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.toolbar {
+    padding-bottom: 10px;
+}
+
+.btns .el-button {
+    margin-left: 10px;
+    margin-bottom: 5px;
+}
+</style>

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/my/index.vue

@@ -10,7 +10,7 @@
           </div>
           <div class="ml-8 profilePicture-text">
             <TranslationComponent :openId="userInfo.userInfo.name" /> <br />
-            <div class="jobIdEtc">工号:{{ userInfo.userInfo.jobNumber }}</div>
+            <div class="jobIdEtc">工号:{{ userInfo.userInfo.jobNumber ? userInfo.userInfo.jobNumber : '待配置' }}</div>
           </div>
         </div>
       </div>

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/team/index.vue

@@ -324,7 +324,7 @@
         </div>
       </template>
       <div class="pt-4 px-12 py-2">
-        同步前请联系企业微信管理员检查应用授权的可见范围路径:管理企业-应用管理-工时管家-可见范围
+        同步前请联系企业微信管理员检查应用授权的可见范围路径:管理企业-应用管理-客户管家-可见范围
       </div>
     </el-dialog>
 

+ 59 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue

@@ -268,7 +268,8 @@
                 工单结算日期{{ obtainMonthlyFinancialModificationDate ? '(修改日期)' : '' }}:
                 <template v-if="!obtainMonthlyFinancialModificationDate">
                   {{ obtainMonthlyFinancialStatementsRows.timesheetDate }}
-                  <el-link type="primary" :underline="false" style="margin-left: 15px;" @click="modificationDate()">修改日期</el-link>
+                  <el-link type="primary" :underline="false" style="margin: 0 15px 0 15px;" @click="modificationDate()">修改日期</el-link>
+                  <el-link type="primary" :underline="false" @click="unallocatedPublicWorkingHours()">查看未分摊公共工时</el-link>
                 </template>
                 <template v-else>
                   <el-date-picker v-model="obtainMonthlyFinancialsRowsDates" type="date" placeholder="选择日期" value-format="yyyy-MM-dd" size="small" :clearable="false" style="margin-right: 15px;width: 160px"></el-date-picker>
@@ -2067,6 +2068,34 @@
             <el-button type="primary" @click="immediate()">确认发送</el-button>
           </span>
         </el-dialog>
+
+        <!-- 查看未分摊公共工时 -->
+        <el-dialog title="查看未分摊公共工时" :visible.sync="unallocatedPublicWorkingHoursVisable" width="680px" top="5.6vh" :before-close="handleClose">
+          <div>
+            <el-table :data="unallocatedPublicWorkingHoursList" border height="400px" style="width: 100%">
+              <el-table-column prop="userReportDeptName" label="部门">
+                <template slot-scope="scope">
+                  <div>
+                    <span v-if="user.userNameNeedTranslate == '1'">
+                      <TranslationOpenDataText type='departmentName' :openid='scope.row.userReportDeptName'></TranslationOpenDataText>
+                    </span>
+                    <span v-if="user.userNameNeedTranslate != '1'">
+                      {{scope.row.userReportDeptName}}
+                    </span>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="workingTime" label="未分摊公共工时(小时)">
+                <template slot-scope="scope">
+                  {{  (scope.row.workingTime || 0).toFixed(2)  }}
+                </template>
+              </el-table-column>
+            </el-table>
+          </div>
+          <span slot="footer" class="dialog-footer">
+            <el-button @click="unallocatedPublicWorkingHoursVisable = false">关闭</el-button>
+          </span>
+        </el-dialog>
   </section>
 </template>
 
@@ -2355,6 +2384,10 @@ export default {
       timelyReportingOfTaskHoursList: [],
       timelyReportingOfTaskHoursLoading: false,
       isItAWorkOrderValue: '',
+
+      unallocatedPublicWorkingHoursVisable: false,
+      unallocatedPublicWorkingHoursList: [],
+      unallocatedPublicWorkingHoursLoading: false,
     };
   },
   computed: {},
@@ -2439,6 +2472,31 @@ export default {
       }
   },
   methods: {
+    unallocatedPublicWorkingHours() {
+      this.unallocatedPublicWorkingHoursVisable = true
+      this.unallocatedPublicWorkingHoursLoading = true
+      this.http.post('/finance-monthly-worktime/getUnDistriibutedPublicTime', {
+        fmwId: this.obtainMonthlyFinancialStatementsRows.id || ''
+      },
+      res => {
+          this.unallocatedPublicWorkingHoursLoading = false
+          if (res.code == "ok") {
+              this.unallocatedPublicWorkingHoursList = res.data || []
+          } else {
+              this.$message({
+              message: res.msg,
+              type: "error"
+              });
+          }
+      },
+      error => {
+          this.unallocatedPublicWorkingHoursLoading = false
+          this.$message({
+              message: error,
+              type: "error"
+          });
+      });
+    },
     expensesSummaries(param) {
       const { columns, data } = param;
         const sums = [];