22 changed files with 5070 additions and 293 deletions
File diff suppressed because it is too large
@ -0,0 +1,140 @@ |
|||||
|
<template> |
||||
|
<view class="render-box shadow-lg block w-full"> |
||||
|
<view |
||||
|
class="render-content block w-full" |
||||
|
:id="`render-${props.task.id}`" |
||||
|
:data-did="props.task.detailId" |
||||
|
:data-param="props.param" |
||||
|
:data-pdu="props.task.planDuration" |
||||
|
:data-pid="project.id" |
||||
|
:data-pstart="props.task.planStart" |
||||
|
:data-rdu="props.task.realDuration" |
||||
|
:data-rid="roleId" |
||||
|
:data-tid="props.task.id" |
||||
|
:data-tname="props.task.name" |
||||
|
:data-token="token" |
||||
|
:data-rstart="props.task.realStart" |
||||
|
:data-uid="userId" |
||||
|
:data-url="project.url" |
||||
|
:data-type="1" |
||||
|
></view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, computed, onMounted, defineProps } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import { getOtherPlugin, getConfigInfo } from 'apis'; |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
task: { default: () => {}, type: Object }, |
||||
|
pluginId: { default: '1', type: String }, |
||||
|
styleType: { default: 0, type: Number }, |
||||
|
pluginTaskId: { default: '', type: String }, |
||||
|
businessPluginId: { default: '', type: String }, |
||||
|
param: { type: String, default: '' }, |
||||
|
}); |
||||
|
|
||||
|
const store = useStore(); |
||||
|
const project = computed(() => store.state.projects.project); // 项目信息 |
||||
|
const userId = computed(() => store.getters['user/userId']); |
||||
|
const roleId = computed(() => store.state.role.roleId); // 当前角色id |
||||
|
const allPlugin = computed(() => store.state.layout.allPlugin); // 所有插件列表 |
||||
|
const businessPlugin = computed(() => store.state.layout.businessPlugin); // 所有服务插件关联 |
||||
|
const token = store.getters['user/token']; |
||||
|
|
||||
|
const pluginInfo = ref(null); |
||||
|
|
||||
|
onMounted(async () => { |
||||
|
await getPlugin(); |
||||
|
if (props.param && pluginInfo.value) { |
||||
|
// const configParam = JSON.parse(props.param); |
||||
|
pluginInfo.value.config = `var p${props.pluginId}_config = ${props.param}`; |
||||
|
} else { |
||||
|
await getConfig(); |
||||
|
} |
||||
|
|
||||
|
if (pluginInfo.value.html) { |
||||
|
// 注意: 截止目前版本2022年1月30日 直接this.pluginTaskId在APP端是不能行的 |
||||
|
// 已向官方提交bug 后期等待修复后 再做调整 |
||||
|
const content = window.document.getElementById(`render-${pluginInfo.value.renderId}`); |
||||
|
content.innerHTML = pluginInfo.value.html; |
||||
|
} |
||||
|
|
||||
|
if (pluginInfo.value.config) { |
||||
|
const scriptConfig = window.document.createElement('script'); |
||||
|
scriptConfig.innerHTML = pluginInfo.value.config; |
||||
|
window.document.body.appendChild(scriptConfig); |
||||
|
} |
||||
|
|
||||
|
if (pluginInfo.value.js) { |
||||
|
const scriptJs = window.document.createElement('script'); |
||||
|
scriptJs.innerHTML = pluginInfo.value.js; |
||||
|
window.document.body.appendChild(scriptJs); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
async function getPlugin() { |
||||
|
const plugins = allPlugin.value || sessionStorage.getItem('allPlugin'); |
||||
|
if (plugins && JSON.parse(plugins)) { |
||||
|
// 有本地数据 |
||||
|
try { |
||||
|
const pluginLists = JSON.parse(plugins); |
||||
|
// pluginLists 可能没有find方法,交给catch处理 |
||||
|
const pluginTarget = pluginLists.find(item => item.id === props.pluginId); |
||||
|
pluginTarget.renderId = props.task.id; |
||||
|
pluginInfo.value = pluginTarget || null; |
||||
|
} catch (error) { |
||||
|
console.error('error: ', error); |
||||
|
pluginInfo.value = null; |
||||
|
} |
||||
|
} else { |
||||
|
// 没有本地数据 API 查询 |
||||
|
const params = { businessPluginId: props.businessPluginId }; |
||||
|
|
||||
|
try { |
||||
|
const res = await getOtherPlugin(params); |
||||
|
res.renderId = props.task.id; |
||||
|
pluginInfo.value = res || null; |
||||
|
} catch (err) { |
||||
|
pluginInfo.value = null; |
||||
|
console.error('err: ', err); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function getConfig() { |
||||
|
const businessPlugins = businessPlugin.value || sessionStorage.getItem('businessPlugin'); |
||||
|
if (businessPlugins && JSON.parse(businessPlugins)) { |
||||
|
// 有本地数据 |
||||
|
const businessPluginLists = JSON.parse(businessPlugins); |
||||
|
businessPluginLists.forEach(item => { |
||||
|
if (item.pluginConfigs) { |
||||
|
const pluginConfig = item.pluginConfigs.find(plugin => plugin.businessPluginId === props.businessPluginId); |
||||
|
if (pluginConfig && pluginConfig.config && pluginInfo.value) { |
||||
|
pluginInfo.value.config = pluginConfig.config; |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} else { |
||||
|
// 没有本地数据 API 查询 |
||||
|
const params = { id: props.businessPluginId }; |
||||
|
|
||||
|
try { |
||||
|
const res = await getConfigInfo(params); |
||||
|
|
||||
|
if (pluginInfo.value && res.config) { |
||||
|
pluginInfo.value.config = res.config; |
||||
|
} |
||||
|
} catch (err) { |
||||
|
console.error('err: ', err); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.render-box { |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,11 @@ |
|||||
|
<template> |
||||
|
<iframe :src="taskDetailUrl" class="w-full h-full"></iframe> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { computed } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
|
||||
|
const store = useStore(); |
||||
|
const taskDetailUrl = computed(() => store.state.task.taskDetailUrl); // iframe详情页链接 |
||||
|
</script> |
||||
@ -0,0 +1,18 @@ |
|||||
|
<template> |
||||
|
<!-- 任务名插件 --> |
||||
|
<div class="u-font-14"> |
||||
|
{{ deliver.deliverName }} |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
// import { useStore } from 'vuex'; |
||||
|
import { ref, inject } from 'vue'; |
||||
|
|
||||
|
// const store = useStore(); |
||||
|
// const task = inject('task'); |
||||
|
const pluginInfo = inject('pluginInfo'); |
||||
|
const deliver = ref(null); // 服务端返回的交付物信息 |
||||
|
|
||||
|
deliver.value = pluginInfo && pluginInfo.data ? JSON.parse(pluginInfo.data) : null; |
||||
|
</script> |
||||
@ -0,0 +1,31 @@ |
|||||
|
import { getAllPlugin, getBusinessPlugin } from 'apis'; |
||||
|
|
||||
|
import { message } from 'ant-design-vue'; |
||||
|
|
||||
|
const actions = { |
||||
|
async getBusinessPlugin({ commit }) { |
||||
|
try { |
||||
|
const res = await getBusinessPlugin(); |
||||
|
sessionStorage.setItem('businessPlugin', JSON.stringify(res) || ''); |
||||
|
commit('setBusinessPlugin', JSON.stringify(res) || ''); |
||||
|
return res; |
||||
|
} catch (error) { |
||||
|
message.info(error.msg); |
||||
|
throw error; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
async getAllPlugin({ commit }) { |
||||
|
try { |
||||
|
const res = await getAllPlugin(); |
||||
|
sessionStorage.setItem('allPlugin', JSON.stringify(res) || ''); |
||||
|
commit('setAllPlugin', JSON.stringify(res) || ''); |
||||
|
return res; |
||||
|
} catch (error) { |
||||
|
message.info(error.msg); |
||||
|
throw error; |
||||
|
} |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
export default actions; |
||||
@ -1,8 +1,10 @@ |
|||||
import state from './state'; |
import actions from './actions'; |
||||
import mutations from './mutations'; |
import mutations from './mutations'; |
||||
|
import state from './state'; |
||||
|
|
||||
export default { |
export default { |
||||
namespaced: true, |
namespaced: true, |
||||
state, |
state, |
||||
mutations, |
mutations, |
||||
|
actions, |
||||
}; |
}; |
||||
|
|||||
@ -0,0 +1,36 @@ |
|||||
|
// 用闭包实现局部对象storage(注意Storage的方法都重写一遍,不然调用其对象原型方法会报错。)
|
||||
|
const sessionStorageMock = (function (win) { |
||||
|
const storage = win.sessionStorage; |
||||
|
return { |
||||
|
setItem(key, value) { |
||||
|
const setItemEvent = new Event('setItemEvent'); |
||||
|
const oldValue = storage[key]; |
||||
|
setItemEvent.key = key; |
||||
|
// 新旧值深度判断,派发监听事件
|
||||
|
if (oldValue !== value) { |
||||
|
setItemEvent.newValue = value; |
||||
|
setItemEvent.oldValue = oldValue; |
||||
|
win.dispatchEvent(setItemEvent); |
||||
|
storage[key] = value; |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
}, |
||||
|
getItem(key) { |
||||
|
return storage[key]; |
||||
|
}, |
||||
|
removeItem(key) { |
||||
|
storage[key] = null; |
||||
|
return true; |
||||
|
}, |
||||
|
clear: () => { |
||||
|
storage.clear(); |
||||
|
return true; |
||||
|
}, |
||||
|
key(index) { |
||||
|
return storage.key(index); |
||||
|
}, |
||||
|
}; |
||||
|
})(window); |
||||
|
|
||||
|
Object.defineProperty(window, 'sessionStorage', { value: sessionStorageMock, writable: true }); |
||||
@ -1,196 +1,33 @@ |
|||||
<template> |
<template> |
||||
<div class="task-detail"> |
<div class="task-detail"> |
||||
<div class="task-con flex"> |
<DetailWebview></DetailWebview> |
||||
|
<!-- <div class="task-con flex"> --> |
||||
<!-- {{ taskInfo.name }} --> |
<!-- {{ taskInfo.name }} --> |
||||
<div class="task-con-box"> |
<!-- <div class="task-con-box"> --> |
||||
<!-- <div>{{ label }}</div> --> |
<!-- <div>{{ label }}</div> --> |
||||
</div> |
|
||||
|
<!-- </div> --> |
||||
|
|
||||
<!-- <div class="task-con-list" v-if="isShowList"> |
<!-- <div class="task-con-list" v-if="isShowList"> |
||||
<TaskConList /> |
<TaskConList /> |
||||
</div> --> |
</div> --> |
||||
</div> |
<!-- </div> --> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<script setup> |
<script setup> |
||||
// import { computed, watch, ref } from 'vue'; |
import DetailWebview from '@/components/tall/Right/DetailWebview.vue'; |
||||
// import { useStore } from 'vuex'; |
|
||||
|
|
||||
// const store = useStore(); |
|
||||
// const taskDetail = computed(() => store.state.task.taskDetail); // 任务名称 |
|
||||
// const label = ref(null); |
|
||||
// const sessionTaskDetail = sessionStorage.getItem('taskDetail'); |
|
||||
// const isShowList = computed(() => store.state.layout.isShowListStatus); // 是否显示任务详情列表 |
|
||||
|
|
||||
// if (sessionTaskDetail) { |
|
||||
// const taskInfo = JSON.parse(sessionTaskDetail); |
|
||||
|
|
||||
// if (taskInfo.plugins && taskInfo.plugins.length > 0) { |
|
||||
// taskInfo.plugins.forEach(item => { |
|
||||
// if (Number(item[0].pluginId) === 1) { |
|
||||
// label.value = item[0].param; |
|
||||
// store.commit('task/setLabel', label.value); |
|
||||
// } |
|
||||
// }); |
|
||||
// } |
|
||||
// } |
|
||||
|
|
||||
// // 监听任务信息 |
|
||||
// watch([taskDetail], () => { |
|
||||
// if (!taskDetail.value) return; |
|
||||
|
|
||||
// const taskInfo = taskDetail.value; |
|
||||
// if (taskInfo.plugins && taskInfo.plugins.length > 0) { |
|
||||
// taskInfo.plugins.forEach(item => { |
|
||||
// if (Number(item[0].pluginId) === 1) { |
|
||||
// label.value = item[0].param; |
|
||||
// store.commit('task/setLabel', label.value); |
|
||||
// } |
|
||||
// }); |
|
||||
// } |
|
||||
// }); |
|
||||
</script> |
</script> |
||||
|
|
||||
<style scoped> |
<style scoped> |
||||
.task-detail { |
.task-detail { |
||||
width: 100%; |
width: 100%; |
||||
height: 100%; |
height: 100%; |
||||
padding: 16px; |
/* padding: 16px; */ |
||||
overflow: auto; |
overflow: auto; |
||||
} |
} |
||||
|
|
||||
.task-con { |
.task-detail::-webkit-scrollbar { |
||||
min-width: 760px; |
width: 0 !important; |
||||
min-height: 500px; |
|
||||
} |
|
||||
|
|
||||
.task-con-box { |
|
||||
max-width: 100%; |
|
||||
flex: 1; |
|
||||
} |
|
||||
|
|
||||
.task-form { |
|
||||
padding: 24px; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
} |
|
||||
|
|
||||
.task-form :deep(.ant-form) { |
|
||||
width: 100%; |
|
||||
max-width: 680px; |
|
||||
} |
|
||||
|
|
||||
.task-con-list { |
|
||||
min-width: 320px; |
|
||||
max-width: 460px; |
|
||||
background: #fff; |
|
||||
border-radius: 10px; |
|
||||
box-shadow: -5px 0px 5px 0px rgba(3, 27, 49, 0.1); |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-input) { |
|
||||
height: 38px; |
|
||||
border: 1px solid #cccccc; |
|
||||
border-radius: 4px; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-btn-primary) { |
|
||||
width: 180px; |
|
||||
height: 38px; |
|
||||
font-size: 16px; |
|
||||
border-radius: 6px; |
|
||||
letter-spacing: 2px; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-space) { |
|
||||
width: 100%; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-picker) { |
|
||||
height: 38px; |
|
||||
width: 100%; |
|
||||
border: 1px solid #cccccc; |
|
||||
border-radius: 4px; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-select-single:not(.ant-select-customize-input) .ant-select-selector) { |
|
||||
height: 38px; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-select-single:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input) { |
|
||||
height: 38px; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-select-single .ant-select-selector .ant-select-selection-item), |
|
||||
:deep(.ant-select-single .ant-select-selector .ant-select-selection-placeholder) { |
|
||||
line-height: 36px; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-upload) { |
|
||||
width: 100%; |
|
||||
} |
|
||||
|
|
||||
/* 上传样式 */ |
|
||||
:deep(.ant-upload) .upload-box { |
|
||||
padding: 20px 0; |
|
||||
border: 1px dashed #cccccc; |
|
||||
background: #fafafa; |
|
||||
border-radius: 4px; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-upload) .upload-box img { |
|
||||
width: 32px; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-upload) .upload-box p:first-of-type { |
|
||||
margin-top: 24px; |
|
||||
line-height: 1; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-upload) .upload-box p:last-of-type { |
|
||||
margin-top: 16px; |
|
||||
line-height: 1; |
|
||||
} |
|
||||
|
|
||||
:deep(.form-item-dad) { |
|
||||
margin-bottom: 0 !important; |
|
||||
} |
|
||||
|
|
||||
.form-item-son { |
|
||||
padding-left: 16px; |
|
||||
} |
|
||||
|
|
||||
/* 表格 */ |
|
||||
:deep(.ant-table-thead > tr > th), |
|
||||
:deep(.ant-table-tbody > tr > td) { |
|
||||
height: 60px; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-table-thead > tr > th) { |
|
||||
background: #fff; |
|
||||
font-size: 16px; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-table-thead |
|
||||
> tr |
|
||||
> th:not(:last-child):not(.ant-table-selection-column):not(.ant-table-row-expand-icon-cell):not([colspan])::before) { |
|
||||
width: 0; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-checkbox-group) { |
|
||||
width: 100%; |
|
||||
} |
|
||||
|
|
||||
/* 单选 */ |
|
||||
:deep(.ant-radio-group) { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
:deep(.ant-radio-wrapper) { |
|
||||
display: flex !important; |
|
||||
} |
} |
||||
</style> |
</style> |
||||
|
|||||
Loading…
Reference in new issue