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 state from './state'; |
|||
|
|||
export default { |
|||
namespaced: true, |
|||
state, |
|||
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> |
|||
<div class="task-detail"> |
|||
<div class="task-con flex"> |
|||
<!-- {{ taskInfo.name }} --> |
|||
<div class="task-con-box"> |
|||
<!-- <div>{{ label }}</div> --> |
|||
</div> |
|||
<DetailWebview></DetailWebview> |
|||
<!-- <div class="task-con flex"> --> |
|||
<!-- {{ taskInfo.name }} --> |
|||
<!-- <div class="task-con-box"> --> |
|||
<!-- <div>{{ label }}</div> --> |
|||
|
|||
<!-- <div class="task-con-list" v-if="isShowList"> |
|||
<!-- </div> --> |
|||
|
|||
<!-- <div class="task-con-list" v-if="isShowList"> |
|||
<TaskConList /> |
|||
</div> --> |
|||
</div> |
|||
<!-- </div> --> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
// import { computed, watch, ref } from '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); |
|||
// } |
|||
// }); |
|||
// } |
|||
// }); |
|||
import DetailWebview from '@/components/tall/Right/DetailWebview.vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.task-detail { |
|||
width: 100%; |
|||
height: 100%; |
|||
padding: 16px; |
|||
/* padding: 16px; */ |
|||
overflow: auto; |
|||
} |
|||
|
|||
.task-con { |
|||
min-width: 760px; |
|||
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; |
|||
.task-detail::-webkit-scrollbar { |
|||
width: 0 !important; |
|||
} |
|||
</style> |
|||
|
|||
Loading…
Reference in new issue