Commit 53185b82 by pangchong

feat: 工作反馈

parent e50ee0c4
import { http } from 'mocp/utils/http'
export const getArrangeWorkListApi = (data, config) => {
return http({
method: 'POST',
url: '/technical-support/getArrangeWorkList',
data,
config
})
}
export const getArrangeWorkDetailApi = (data, config) => {
return http({
method: 'POST',
url: '/technical-support/getArrangeWorkDetail',
data,
config
})
}
export const savaArrangeWorkFeedbackApi = (data, config) => {
return http({
method: 'POST',
url: '/technical-support/savaArrangeWorkFeedback',
data,
config
})
}
......@@ -24,3 +24,11 @@ export const getAdminListApi = (data, config) => {
config
})
}
export const getBasicParamsListApi = (data, config) => {
return http({
method: 'POST',
url: '/resource/getBasicParamsList',
data,
config
})
}
......@@ -64,7 +64,7 @@ const ps = defineProps({
},
format: {
type: String,
default: 'YYYY-MM-DD'
default: 'YYYY/MM/DD'
},
cancelText: {
type: String,
......
......@@ -113,14 +113,16 @@ const queryList = (pageIndex, pageSize) => {
}
const params = {
pageIndex,
pageSize,
[ps.tabValueField]: ps.tabValue
pageSize
}
if (ps.tabValue) {
params[ps.tabValueField] = ps.tabValue
}
if (Object.prototype.toString.call(ps.api) == '[object Function]') {
ps.api(params, { loading: true })
.then((res) => {
if (res.code == 200) {
paging.value?.complete(res.list || [])
paging.value?.complete(res.list || res.data?.list || [])
firstLoaded.value = true
} else {
uni.$mocpMessage.showToast(res.message)
......@@ -138,6 +140,9 @@ const queryList = (pageIndex, pageSize) => {
defineExpose({
reload: () => {
paging.value?.reload()
},
updateCache: () => {
paging.value?.updateCache()
}
})
</script>
......
......@@ -188,6 +188,9 @@ const pagingArr = ref([])
defineExpose({
reload: () => {
pagingArr.value[current.value]?.reload()
},
updateCache: () => {
pagingArr.value[current.value]?.updateCache()
}
})
</script>
......
......@@ -15,3 +15,11 @@ export const eventType = [
{ label: '扣分', value: 0 },
{ label: '加分', value: 1 }
]
export const feedbackOpts = [
{ label: '是', value: 1 },
{ label: '落实执行', value: 0 }
]
export const feedbackState = [
{ label: 'OPEN', value: 1 },
{ label: 'CLOSE', value: 2 }
]
......@@ -14,15 +14,15 @@
<slot name="title" v-if="title">
<view class="title">{{ title }}</view>
</slot>
<view class="content">
<scroll-view scroll-y class="content" :scroll-top="scrollTop" @scroll="scroll">
<slot></slot>
</view>
</scroll-view>
</view>
</up-popup>
</template>
<script setup>
import { computed } from 'vue'
import { computed, nextTick, ref, watch } from 'vue'
const es = defineEmits(['close', 'open'])
const ps = defineProps({
......@@ -89,6 +89,23 @@ const getCustomStyle = computed(() => {
}
return style
})
//控制滚动区域
const scrollTop = ref(0)
const oldScrollTop = ref(0)
const scroll = (e) => {
oldScrollTop.value = e.detail.scrollTop
}
watch(
() => ps.modelValue,
(value) => {
if (value) {
scrollTop.value = 0
nextTick(() => {
scrollTop.value = oldScrollTop.value
})
}
}
)
const close = () => {
es('close', false)
}
......
......@@ -39,7 +39,7 @@ const ps = defineProps({
},
url: {
type: String,
default: ''
default: '/resource/uploadFile'
},
uploadIcon: {
type: String,
......
......@@ -32,7 +32,6 @@ const useAppraisalRecordStore = defineStore('appraisalRecord', {
if (res.code == 200) {
this.details = res.data
this.details.file = JSON.parse(res.data.file)
this.details.eventTime = String(res.data.eventTime)
} else {
uni.$mocpMessage.showToast(res.message)
}
......
import { getArrangeWorkDetailApi } from 'mocp/api/assign-work'
import { defineStore } from 'pinia'
const useAssignWorkStore = defineStore('assignWork', {
state: () => {
return {
id: '',
details: undefined,
arrangeWorkExtendList: [], //责任单位列表
arrangeWorkExtend: undefined //当前选中的责任单位
}
},
getters: {
//获取分解计划
getDecompose(state) {
return JSON.parse(state.arrangeWorkExtend?.decompose || '[]') || []
}
},
actions: {
async getArrangeWorkDetail() {
const res = await getArrangeWorkDetailApi({ id: this.id }, { loading: true })
if (res.code == 200) {
this.details = res.data
this.arrangeWorkExtendList = res.data.arrangeWorkExtendList || []
this.arrangeWorkExtend = res.data.arrangeWorkExtendList[0]
} else {
uni.$mocpMessage.showToast(res.message)
}
},
setState(...args) {
this.$patch({ [args[0]]: args[1] })
}
},
// 配置持久化
persist: {
// 调整为兼容多端的API
storage: {
setItem(key, value) {
uni.setStorageSync(key, value)
},
getItem(key) {
return uni.getStorageSync(key)
}
}
}
})
export default useAssignWorkStore
import { getAircraftNumbersApi } from 'mocp/api/base'
import { getAircraftNumbersApi, getBasicParamsListApi } from 'mocp/api/base'
import { defineStore } from 'pinia'
const useBaseStore = defineStore('base', {
......@@ -6,19 +6,56 @@ const useBaseStore = defineStore('base', {
return {
selectList: {
deviceNumSelect: [] //机号
}
},
allBasicParams: {}
}
},
getters: {},
actions: {
initSysData() {
this.getAircraftNumbers()
this.getBasicParamsList()
},
async getAircraftNumbers() {
const res = await getAircraftNumbersApi({})
if (res.code == 200) {
this.selectList.deviceNumSelect = res.data
}
},
async getBasicParamsList() {
const res = await getBasicParamsListApi({})
if (res.code == 200) {
this.allBasicParams = res.data.reduce((q, w) => {
if (!q[w.paramType]) {
q[w.paramType] = []
}
q[w.paramType].push(w)
return q
}, {})
}
},
getParamsByType(paramType) {
return this.allBasicParams[paramType]
.filter((item) => item.isDel == 0)
.map((item) => {
return { label: item.paramName, value: item.paramCode }
})
},
getParamNameByValue(paramType, paramName) {
return this.getParamsByType(paramType).find((item) => item.value == paramName)?.label || ''
}
},
// 配置持久化
persist: false
persist: {
// 调整为兼容多端的API
storage: {
setItem(key, value) {
uni.setStorageSync(key, value)
},
getItem(key) {
return uni.getStorageSync(key)
}
}
}
})
export default useBaseStore
......@@ -45,7 +45,7 @@ const httpInterceptor = (options) => {
options.data = {
...options.data,
apiPwd: 'Ifar$2_0160_525_Mocp',
requestFrom: '3',
requestFrom: '6',
realUserId: userStore.userInfo?.id
}
}
......
......@@ -10,6 +10,6 @@ export const timeStampFormat = (timeStamp, opt) => {
return ''
}
timeStamp = parseInt(String(timeStamp))
const format = opt?.format || 'YYYY-MM-DD HH:mm:ss'
const format = opt?.format || 'YYYY/MM/DD'
return Day(timeStamp).format(format)
}
......@@ -25,7 +25,7 @@
</view>
<view class="label">
<global-icon icon="calendar" color="#1D2129"></global-icon>
<text class="txt">{{ calendar != -1 ? timeStampFormat(calendar) : '-' }}</text>
<text class="txt">{{ calendar != -1 ? timeStampFormat(calendar, { format: 'YYYY/MM/DD HH:mm:ss' }) : '-' }}</text>
</view>
</view>
</slot>
......
import { reactive, ref } from 'vue'
export const formRef = ref()
......
......@@ -16,7 +16,7 @@
<global-icon class="left-icon" icon="Vector" size="24" color="#DD4012"></global-icon>
<view class="txt">{{ details.ac }} {{ details.acType }}</view>
</view>
<view class="right">{{ timeStampFormat(details.eventTime, { format: 'YYYY-MM-DD' }) }}</view>
<view class="right">{{ timeStampFormat(details.eventTime) }}</view>
</view>
</view>
<view class="details-body">
......
......@@ -119,7 +119,7 @@
<global-picker pickAlign="right" dictkey="appealInfo" v-model="formData.appealInfo" clearable></global-picker>
</view>
<view class="appeal-content">
<global-upload :fileList="getFileList" url="/resource/uploadFile" @handleUpload="handleUpload"></global-upload>
<global-upload :fileList="getFileList" @handleUpload="handleUpload"></global-upload>
</view>
</view>
</view>
......@@ -159,7 +159,7 @@ onShow(() => {
formData.dmUid = details.value.dmUid
formData.eventMsg = details.value.eventMsg
formData.eventSource = details.value.eventSource
formData.eventTime = details.value.eventTime
formData.eventTime = String(details.value.eventTime)
formData.eventType = details.value.eventType
formData.examineBasis = details.value.examineBasis
formData.examineType = details.value.examineType
......
......@@ -34,7 +34,6 @@ const ps = defineProps({
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 0;
border-bottom: 2rpx solid #f4f4f4;
margin-top: 16rpx;
}
</style>
<template>
<view class="card-details-item">
<view class="card-details-item" :class="{ borderBottom }">
<view class="title" v-if="title">{{ title }}</view>
<view class="label" v-if="label">{{ label }}</view>
<view class="content">{{ content }}</view>
<slot></slot>
</view>
</template>
<script setup>
const ps = defineProps({
borderBottom: {
type: Boolean,
default: true
},
title: {
type: String,
default: ''
......@@ -24,8 +29,11 @@ const ps = defineProps({
</script>
<style lang="scss" scoped>
.card-details-item {
border-bottom: 2rpx solid #f4f4f4;
padding: 16rpx 0;
padding-top: 16rpx;
&.borderBottom {
padding-bottom: 16rpx;
border-bottom: 2rpx solid #f4f4f4;
}
.title {
font-size: 34rpx;
color: $mocp-text-5;
......
<template>
<global-popup v-model="showPopup" mode="right" :width="580" background="#F7F8FA" title="选择责任单位" :round="32" @close="showPopup = false">
<view class="list">
<view class="item" v-for="item in 100" :key="item" @tap="handleClick">中南维修基地</view>
<view class="item" v-for="item in arrangeWorkExtendList" :key="item.id" @tap="handleClick(item)">
{{ item.companyFullName }}
</view>
</view>
</global-popup>
</template>
<script setup>
import { ref } from 'vue'
import useAssignWorkStore from 'mocp/store/assign-work'
import { storeToRefs } from 'pinia'
const assignWorkStore = useAssignWorkStore()
const { arrangeWorkExtendList } = storeToRefs(assignWorkStore)
const showPopup = ref(false)
const open = () => {
showPopup.value = true
}
//切换责任公司
const handleClick = () => {
const handleClick = (row) => {
showPopup.value = false
assignWorkStore.setState('arrangeWorkExtend', row)
uni.$mocpMessage.showToast('已切换成' + row.companyFullName)
}
defineExpose({
open
......
......@@ -3,6 +3,11 @@
color: $mocp-text-4;
background: #fff;
&-header {
&-title {
font-size: 48rpx;
color: $mocp-text-5;
margin-bottom: 16rpx;
}
&-top {
display: flex;
align-items: center;
......@@ -16,9 +21,6 @@
}
}
&-center {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 16rpx;
.left {
.txt {
......@@ -26,6 +28,10 @@
}
}
.right {
margin-top: 16rpx;
display: flex;
align-items: center;
justify-content: space-between;
.txt {
margin-left: 16rpx;
}
......
import { reactive, ref } from 'vue'
export const fileVoList = ref([]) //分解计划文件
export const approvalFileVoList = ref([]) //工作反馈文件
export const formData = reactive({
problem: '',
workTarget: '',
current: '',
baseApprovalLeader: '',
mcdApprovalLeader: '',
followUpFeedback: '0',
pcTime: null,
feedbackState: null,
feedbackUser: '',
feedbackTime: ''
})
export const rules = reactive({
feedbackState: [
{
type: 'number',
required: true,
message: '请选择工作反馈状态',
trigger: ['blur', 'change']
}
],
problem: [
{
required: true,
message: '请输入问题分析',
trigger: ['blur', 'change']
}
],
workTarget: [
{
required: true,
message: '请输入解决措施',
trigger: ['blur', 'change']
}
],
current: [
{
required: true,
message: '请输入当前进展',
trigger: ['blur', 'change']
}
],
baseApprovalLeader: [
{
required: true,
message: '请输入基地/部门批准领导',
trigger: ['blur', 'change']
}
],
mcdApprovalLeader: [
{
required: true,
message: 'MCD批准领导',
trigger: ['blur', 'change']
}
],
followUpFeedback: [
{
required: true,
message: '请选择后续措施反馈',
trigger: ['blur', 'change']
}
],
pcTime: [
{
type: 'number',
required: true,
message: '请选择计划完成时间',
trigger: ['blur', 'change']
}
]
})
import { approvalFileVoList, fileVoList } from './edit-work.compositions'
export const handleUploadFile = (data) => {
fileVoList.value = data
}
export const handleUploadApproval = (data) => {
approvalFileVoList.value = data
}
......@@ -33,13 +33,10 @@
line-height: 40rpx;
}
&-footer {
margin-top: 16rpx;
display: flex;
align-items: center;
justify-content: space-between;
.label {
display: flex;
align-items: center;
margin-top: 16rpx;
.txt {
margin-left: 16rpx;
}
......
......@@ -5,38 +5,36 @@
:showNavRight="true"
navRightType="button"
navRightText="保存"
@handleRightClick="handleSave"
showFooterBtn
footerBtnText="添加分解计划"
@handleFooterClick="handleFooterClick"
>
<view class="mocp-form">
<up-form labelPosition="left" labelWidth="auto" ref="formRef">
<view class="form">
<up-form-item label="分解计划1" :borderBottom="true" labelPosition="top">
<view class="delete" @tap="handleDelete"><global-icon icon="delete-01" color="#F53F3F"></global-icon></view>
<up-textarea
placeholder="一段很长很长的内容文字,长文本自动换行,该选项的描述是一段很长的内容"
:height="40"
border="none"
></up-textarea>
</up-form-item>
<up-form-item label="完成时限" :borderBottom="true">
<global-date pickAlign="right" clearable :emptyValue="-1" placeholder="请选择日期"></global-date>
</up-form-item>
</view>
<view class="form">
<up-form-item label="分解计划2" :borderBottom="true" labelPosition="top">
<view class="delete" @tap="handleDelete"><global-icon icon="delete-01" color="#F53F3F"></global-icon></view>
<up-textarea
placeholder="一段很长很长的内容文字,长文本自动换行,该选项的描述是一段很长的内容"
:height="40"
border="none"
></up-textarea>
</up-form-item>
<up-form-item label="完成时限" :borderBottom="true">
<global-date pickAlign="right" clearable :emptyValue="-1" placeholder="请选择日期"></global-date>
</up-form-item>
</view>
<up-form labelPosition="left" labelWidth="auto">
<template v-for="(item, index) in formData" :key="index">
<view class="form">
<up-form-item
:label="formData.length > 1 ? '分解计划' + (index + 1) : '分解计划'"
:borderBottom="true"
labelPosition="top"
required
>
<view class="delete" v-if="formData.length > 1" @tap="handleDelete(index)">
<global-icon icon="delete-01" color="#F53F3F"></global-icon>
</view>
<up-textarea
v-model="item.plan"
placeholder="一段很长很长的内容文字,长文本自动换行,该选项的描述是一段很长的内容"
:height="40"
border="none"
></up-textarea>
</up-form-item>
<up-form-item label="完成时限" :borderBottom="true">
<global-date pickAlign="right" clearable placeholder="请选择日期" v-model="item.time" emptyValue="null"></global-date>
</up-form-item>
</view>
</template>
</up-form>
</view>
<up-modal
......@@ -54,14 +52,45 @@
<script setup>
import { ref } from 'vue'
import { cloneDeep } from 'lodash'
const formData = ref([])
//初始化数据
uni.$on('sendDecompose', (data) => {
if (data.length) {
formData.value = cloneDeep(data)
} else {
formData.value.push({ plan: '', time: null })
}
})
const show = ref(false)
const handleDelete = () => {
const currentIndex = ref(-1)
//删除
const handleDelete = (index) => {
show.value = true
currentIndex.value = index
}
//确认删除
const confirm = () => {
formData.value.splice(currentIndex.value, 1)
show.value = false
currentIndex.value = -1
}
//保存
const handleSave = async () => {
const planIndex = formData.value.findIndex((item) => item.plan.trim() === '')
if (planIndex > -1) {
if (formData.value.length > 1) {
return uni.$mocpMessage.showToast(`请输入分解计划${planIndex + 1}的内容`)
} else {
return uni.$mocpMessage.showToast(`请输入分解计划的内容`)
}
}
uni.$emit('changeDecompose', formData.value)
uni.$mocpJump.navigateBack()
}
const confirm = () => {}
const handleFooterClick = () => {
console.log('点击了添加分解计划')
formData.value.push({ plan: '', time: null })
}
</script>
<style lang="scss" scoped>
......
......@@ -11,7 +11,7 @@
</up-form-item>
<up-form-item label="验证材料" labelPosition="top" :borderBottom="true">
<view style="margin-top: 24rpx">
<global-upload url="/resource/uploadFile"></global-upload>
<global-upload></global-upload>
</view>
</up-form-item>
<up-form-item label="应用分类" :borderBottom="true">
......
......@@ -17,7 +17,7 @@
</up-form-item>
<up-form-item label="验证附件" labelPosition="top" :borderBottom="true">
<view style="margin-top: 24rpx">
<global-upload url="/resource/uploadFile"></global-upload>
<global-upload></global-upload>
</view>
</up-form-item>
<up-form-item label="工作验证状态" :borderBottom="true">
......
<template>
<global-page-swiper title="布置工作" refresherEnabled loadingMoreEnabled :tabList="tabList" :api="getRqmListApi" ref="paging" :padding="24">
<global-page-swiper
title="布置工作"
refresherEnabled
loadingMoreEnabled
:tabList="tabList"
:api="getArrangeWorkListApi"
:padding="24"
tabValueField="state"
>
<template #="{ dataList }">
<view class="item" v-for="item in dataList" :key="item.id" @tap="goDetails(item)">
<view class="item-title">
<view class="left">
<view class="type">{{ item.status == 1 ? 'OPEN' : 'ClOSE' }}</view>
<view class="txt">早会工作详情</view>
<view class="type">{{ item.state == 1 ? 'OPEN' : 'ClOSE' }}</view>
<view class="txt u-line-1">{{ baseStore.getParamNameByValue('LayoutWorkType', item.workType) }}详情</view>
</view>
<view class="right">早会工作</view>
<view class="right u-line-1">{{ baseStore.getParamNameByValue('LayoutWorkType', item.workType) }}</view>
</view>
<view class="item-content u-line-3">
海航技术专项布置〔2024〕00022号: 首6709飞机1月10日广州航前有AC ESS
BUSSHED信息,同时左侧MCDU和ND黑屏,断电重启无效,排故所需8XH和9XH继电器集团无料的情况,要求采购管理部对使用及库存情况进行核实,尽快安排采购配备。
{{ item.taskDescribe }}
</view>
<view class="item-footer">
<view class="label">
<global-icon icon="calendar"></global-icon>
<text class="txt">2024-01-10</text>
<text class="txt">
{{ timeStampFormat(item.startTime) }}
-
{{ timeStampFormat(item.feedbackTime) }}
</text>
</view>
<view class="label">
<global-icon icon="idcard"></global-icon>
<text class="txt">陈朝丽测试</text>
<text class="txt">{{ item.presenter }}</text>
</view>
</view>
</view>
......@@ -30,32 +41,20 @@
<script setup>
import { ref } from 'vue'
import { getRqmListApi } from 'mocp/api/appraisal-record'
import { onLoad, onUnload } from '@dcloudio/uni-app'
import useAppraisalRecordStore from 'mocp/store/appraisal-record'
import useBaseStore from 'mocp/store/base'
import { timeStampFormat } from 'mocp/utils/tool'
import { getArrangeWorkListApi } from 'mocp/api/assign-work'
const tabList = ref([
{ name: 'OPEN', value: 1 },
{ name: 'CLOSE', value: 0 },
{ name: '全部', value: -1 }
{ name: 'CLOSE', value: 2 },
{ name: '全部', value: null }
])
const baseStore = useBaseStore()
//跳转
const goDetails = (data) => {
uni.$mocpJump.navigateTo('/panel/assign-work/details', { id: data.id })
}
//加载下拉框数据
const appraisalRecordStore = useAppraisalRecordStore()
onLoad(() => {
appraisalRecordStore.getRqmOptions()
})
//刷新
const paging = ref()
uni.$on('appraisalRecordReload', () => {
paging.value?.reload()
})
onUnload(() => {
uni.$off('appraisalRecordReload')
})
</script>
<style lang="scss" scoped>
@import './constants/list.scss';
......
......@@ -33,7 +33,7 @@
<script setup>
import { ref } from 'vue'
import MenuItem from './components/menu-item.vue'
import MenuItem from './menu-item.vue'
import useUserStore from 'mocp/store/user'
const userStore = useUserStore()
......@@ -59,5 +59,5 @@ const goAppCenter = () => {
}
</script>
<style lang="scss" scoped>
@import './constants/panel-menu.scss';
@import '../constants/panel-menu.scss';
</style>
......@@ -36,5 +36,5 @@
<script setup></script>
<style lang="scss" scoped>
@import './constants/panel-navbar.scss';
@import '../constants/panel-navbar.scss';
</style>
......@@ -11,12 +11,13 @@
</template>
<script setup>
import PanelNavbar from './panel-navbar.vue'
import PanelMenu from './panel-menu.vue'
import PanelNavbar from './components/panel-navbar.vue'
import PanelMenu from './components/panel-menu.vue'
import useBaseStore from 'mocp/store/base'
//加载基础参数
const baseStore = useBaseStore()
baseStore.getAircraftNumbers()
baseStore.initSysData()
</script>
<style lang="scss" scoped>
.page-bg {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment