Commit 7cab68d9 by chehuidong

Merge branch 'taskManage' into 'dev'

Task manage

See merge request !2
parents 80cc2748 c8e002c5
......@@ -17,5 +17,8 @@ module.exports = {
'space-before-function-paren': 'off',
indent: 'off',
'multiline-ternary': 'off',
"vue/multi-word-component-names":"off",
'eol-last': 0,
'vue/no-mutating-props':"off"
},
}
......@@ -2,7 +2,7 @@
node_modules
/dist
package-lock.json
# local env files
.env.local
.env.*.local
......
{
"tabWidth": 2,
"singleQuote": true,
"printWidth": 80,
"semi": false,
"trailingComma": "none",
"bracketSpacing": true,
"bracketSameLine": true,
"arrowParens": "always",
"htmlWhitespaceSensitivity": "ignore"
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -8,6 +8,8 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^1.0.2",
"axios": "^1.1.3",
"core-js": "^3.8.3",
"element-ui": "^2.15.10",
......
window.apiHostSetting = {
VUE_APP_BASE_URL: '',
VUE_APP_BASE_URL: 'https://dbh.joshine.cn',
}
import axios from './axios'
export function getLoginState({ userName, password }) {
return axios.post('sys/saasUserLogin/login', null, {
params: { userName, password },
})
export function getLoginState({ account, password }) {
return axios.post('platform/user/login', { account, password })
}
export function logout() {
return axios.get('sys/saasUserLogin/logout')
return axios.get('platform/user/logout')
}
import axios from './axios'
export function uploadImg(file, params = {}) {
const from = new FormData()
from.append('file', file)
const { url, ...otherParams } = params
for (const key in otherParams) {
from.append(key, otherParams[key])
}
return axios.post(url || 'upload/fileUpload/images', from, {
headers: { 'content-type': 'multipart/form-data' },
})
}
\ No newline at end of file
......@@ -61,3 +61,15 @@
.el-dialog__body {
padding: 10px;
}
.pagination {
text-align: center;
padding-top: 10px;
}
.icon-view{
font-size: 18px;
cursor: pointer;
}
.icon-view + .icon-view{
margin-left: 10px;
}
\ No newline at end of file
<script>
function getStartTime() {
const date = new Date()
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
return `${year}-${month}-${day} 00:00:00`
}
const pickerOptions = {
shortcuts: [
{
text: '今日',
onClick(picker) {
const start = new Date(
new Date(getStartTime()).getTime(),
)
const end = new Date()
picker.$emit('pick', [start, end])
},
},
{
text: '昨天',
onClick(picker) {
const start = new Date()
const end = new Date(
new Date(getStartTime()).getTime() - 1,
)
start.setTime(
end.getTime() - 3600 * 1000 * 24 * 1 + 1,
)
console.log(start, end)
picker.$emit('pick', [start, end])
},
},
{
text: '最近7天',
onClick(picker) {
const end = new Date()
const start = new Date(getStartTime())
start.setTime(
start.getTime() - 3600 * 1000 * 24 * 6,
)
picker.$emit('pick', [start, end])
},
},
{
text: '最近14天',
onClick(picker) {
const end = new Date()
const start = new Date(getStartTime())
start.setTime(
start.getTime() - 3600 * 1000 * 24 * 13,
)
picker.$emit('pick', [start, end])
},
},
{
text: '最近30天',
onClick(picker) {
const end = new Date()
const start = new Date(getStartTime())
start.setTime(
start.getTime() - 3600 * 1000 * 24 * 29,
)
picker.$emit('pick', [start, end])
},
},
{
text: '本星期',
onClick(picker) {
const end = new Date()
const start = new Date()
const nowDay = new Date().getDay() - 1
start.setTime(
new Date(getStartTime()).getTime() -
3600 * 1000 * 24 * nowDay,
)
picker.$emit('pick', [start, end])
},
},
{
text: '上星期',
onClick(picker) {
const end = new Date()
const start = new Date()
const nowDay = new Date().getDay() - 1
end.setTime(
new Date(getStartTime()).getTime() -
3600 * 1000 * 24 * nowDay -
1,
)
start.setTime(
end.getTime() - 3600 * 1000 * 24 * 7 + 1,
)
picker.$emit('pick', [start, end])
},
},
{
text: '这个月',
onClick(picker) {
const end = new Date()
const start = new Date()
const nowDate = new Date().getDate() - 1
start.setTime(
new Date(getStartTime()).getTime() -
3600 * 1000 * 24 * nowDate,
)
picker.$emit('pick', [start, end])
},
},
{
text: '上个月',
onClick(picker) {
const date = new Date()
let year = date.getFullYear()
let month = date.getMonth()
const end = new Date(
new Date(
`${year}-${month + 1}-1 00:00:00`,
).getTime() - 1,
)
if (month === 0) {
month = 12
year = year - 1
}
const start = new Date(
new Date(`${year}-${month}-1 00:00:00`).getTime(),
)
picker.$emit('pick', [start, end])
},
},
{
text: '历史',
onClick(picker) {
picker.$emit('pick', ['', ''])
},
},
],
}
export default {
name: 'choose-time-period',
props: {
periodTime: {
type: Array,
default: () => {},
},
clearable: {
type: Boolean,
default: true,
},
placeholder: {
type: String,
default: '时间',
},
format: {
type: String,
default: 'yyyy-MM-dd HH:mm:ss',
},
type: {
type: String,
default: 'datetimerange',
},
align: {
type: String,
default: 'left',
},
},
model: {
prop: 'periodTime',
event: 'setVal',
},
render() {
return (
<el-date-picker
type={this.type}
value={this.periodTime}
clearable={this.clearable}
onInput={(v) => this.$emit('setVal', v)}
range-separator="-"
value-format={this.format}
start-placeholder={`开始${this.placeholder}`}
end-placeholder={`结束${this.placeholder}`}
style="width:200px"
default-time={['00:00:00', '23:59:59']}
picker-options={pickerOptions}
align={this.align}
></el-date-picker>
)
},
}
</script>
<!--
* @Description: 描述
* @Author: chd
* @Date: 2021-02-01 10:24:15
* @LastEditors: chd
* @LastEditTime: 2021-07-02 14:42:27
-->
<script>
export default {
name: 'status-list',
data() {
return {
statusCode: '',
}
},
mounted() {
if (!this.statusCode && this.statuslist.length > 0) {
this.statusCode = this.statuslist[this.defauntIndex].statusCode
}
},
props: {
statuslist: {
type: Array,
defaunt: () => {},
},
defauntIndex: {
type: Number,
defaunt: 0,
},
isHide: {
type: Boolean,
defaunt: false,
},
},
watch: {
statuslist(list) {
if (
!this.statusCode &&
this.defauntIndex !== null &&
this.defauntIndex !== undefined
) {
this.statusCode = list[this.defauntIndex].statusCode
}
if (
this.isHide &&
this.defauntIndex !== null &&
this.defauntIndex !== undefined
) {
this.statusCode = list[this.defauntIndex].statusCode
}
},
},
methods: {
setTabIndex(item, index) {
this.statusCode = item.statusCode
this.$emit('statusChange', { item, index })
},
changeStatusCode(code) {
this.statusCode = code
},
},
render() {
const elItem = (item, index) => (
<li
key={item.statusCode}
style={
this.isHide
? {
display: index !== 0 && item.quantity === 0 ? 'none' : 'block',
}
: { display: item.show === false ? 'none' : 'block' }
}
onClick={() => this.setTabIndex(item, index)}
class={`tabs-item ${
this.statusCode === item.statusCode ? 'active' : ''
}`}>
{item.statusName}({item.quantity})
<span class="right_btn">
{this.$scopedSlots.operate && this.$scopedSlots.operate(item)}
</span>
</li>
)
return (
<ul>
{this.statuslist.map((item, index) => {
if (item.children) {
return (
<div key={index}>
{elItem(item, index)}
<ul style="margin-left:1em">
{item.children.map((item1, index1) => {
if (item1.children) {
return (
<div key={item1.statusCode}>
{elItem(item1, index1)}
<ul style="margin-left:1em">
{item1.children.map((item2, index2) => {
return elItem(item2, index2)
})}
</ul>
</div>
)
} else {
return elItem(item1, index1)
}
})}
</ul>
</div>
)
} else {
return elItem(item, index)
}
})}
</ul>
)
},
}
</script>
<style scoped>
.tabs-item {
font-size: 14px;
padding: 5px 10px 5px 20px;
cursor: pointer;
position: relative;
}
.tabs-item:hover,
.tabs-item.active {
color: #4168FF;
background: #ddd;
}
.subtitle {
margin-left: 1em;
}
.right_btn {
display: none;
position: absolute;
top: 0;
right: 0;
}
.tabs-item:hover .right_btn {
display: block;
}
</style>
class EditSourceCode {
constructor() {
this.title = '代码' // 自定义菜单标题
this.iconSvg = `<svg
t="1644825421859"
class="active"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="9348" width="18" height="18">
<path
d="M875.52 89.6H148.48c-33.792 0-61.44 27.648-61.44 61.44v721.92c0 33.792 27.648 61.44 61.44 61.44h727.04c33.792 0 61.44-27.648 61.44-61.44v-721.92c0-33.792-27.648-61.44-61.44-61.44z m20.48 783.36c0 11.1104-9.3696 20.48-20.48 20.48H148.48c-11.1104 0-20.48-9.3696-20.48-20.48v-568.32h768v568.32z m0-609.28H128v-112.64c0-11.1104 9.3696-20.48 20.48-20.48h727.04c11.1104 0 20.48 9.3696 20.48 20.48v112.64z"
fill="#1e88e5" p-id="9349"></path>
<path
d="M215.04 204.8m-20.48 0a20.48 20.48 0 1 0 40.96 0 20.48 20.48 0 1 0-40.96 0Z"
fill="#1e88e5" p-id="9350"></path>
<path d="M291.84 204.8m-20.48 0a20.48 20.48 0 1 0 40.96 0 20.48 20.48 0 1 0-40.96 0Z"
fill="#1e88e5" p-id="9351">
</path><path
d="M368.64 204.8m-20.48 0a20.48 20.48 0 1 0 40.96 0 20.48 20.48 0 1 0-40.96 0Z"
fill="#1e88e5" p-id="9352"></path>
<path d="M196.7616 621.6192l129.8432 129.8432c6.912 6.912 17.8688 8.5504 26.0608 3.2256 11.2128-7.3728 12.3904-22.7328 3.3792-31.6928L243.8656 610.816c-2.816-2.816-2.816-7.3216 0-10.0864L355.584 488.96c6.912-6.912 8.5504-17.8688 3.2256-26.0608-7.3728-11.2128-22.7328-12.3904-31.6928-3.3792L196.7616 589.824c-4.352 4.352-11.3664 10.1888-10.9568 15.872-0.3584 5.7344 6.656 11.5712 10.9568 15.9232zM780.1344 600.6784c2.816 2.816 2.816 7.3216 0 10.0864l-112.1792 112.1792c-8.96 8.96-7.8336 24.3712 3.3792 31.6928 8.192 5.3248 19.1488 3.6864 26.0608-3.2256l129.8432-129.8432c4.352-4.352 11.3664-10.1888 10.9568-15.872 0.4096-5.6832-6.6048-11.52-10.9568-15.872l-130.304-130.304c-8.96-8.96-24.3712-7.8336-31.6928 3.3792-5.3248 8.192-3.6864 19.1488 3.2256 26.0608l111.6672 111.7184zM430.2336 786.432c10.1888 4.8128 22.4768 0.4096 27.2896-9.7792l146.0224-308.8896c4.8128-10.1888 0.4096-22.4768-9.7792-27.2896a20.56704 20.56704 0 0 0-27.2896 9.7792l-146.0224 308.8896a20.56704 20.56704 0 0 0 9.7792 27.2896z"
fill="#1e88e5"
p-id="9353"></path>
</svg>` // 可选
this.tag = 'button'
this.active = false
}
// 获取菜单执行时的 value ,用不到则返回空 字符串或 false
getValue(editor) {
return this.active ? editor.getText() : editor.getHtml()
}
// 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false
isActive() {
return this.active
}
// 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
isDisabled() {
return false
}
// 点击菜单时触发的函数
exec(editor, value) {
if (this.isDisabled(editor)) return
console.log(value)
this.active = !this.active
if (this.active) {
value = value
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/ /g, '&nbsp;')
} else {
value = value
.replace(/&lt;/gi, '<')
.replace(/&gt;/gi, '>')
.replace(/&nbsp;/gi, ' ')
}
console.log(value)
editor.setHtml(value) // value 即 this.value(editor) 的返回值
}
}
const editCode = {
key: 'editCode', // 定义 menu key :要保证唯一、不重复(重要)
factory() {
return new EditSourceCode() // 把 `YourMenuClass` 替换为你菜单的 class
},
}
export default editCode
import { Boot } from '@wangeditor/editor'
import editCode from './code'
import insetSelect from './inset'
const module = {
menus: [editCode, insetSelect],
}
Boot.registerModule(module)
function insertKeys(isInsert) {
if (isInsert) {
return {
index: -2,
keys: ['editCode', 'insertSelect'],
}
}
return {
index: -1,
keys: ['editCode'],
}
}
export default insertKeys
\ No newline at end of file
<template>
<div style="border: 1px solid #ccc; z-index: 9999">
<Toolbar
class="editor_toolbar"
style="border-bottom: 1px solid #ccc"
:editor="editor"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<Editor
style="height: 300px; overflow-y: hidden"
v-model="html"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="onCreated"
/>
</div>
</template>
<script>
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import '@wangeditor/editor/dist/css/style.css'
import insertKeys from './index'
import { uploadImg } from '../../common/api/upload'
export default {
components: { Editor, Toolbar },
data() {
return {
editor: null,
mode: 'default',
}
},
model: {
prop: 'content',
event: 'change',
},
props: {
content: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '',
},
isInsert: {
type: Boolean,
default: false,
},
insertData: {
type: Array,
default: () => [
{
label: '客户名称',
value: '{payerName} {payerSurname}',
},
{ label: '订单编号', value: '{id}' },
{ label: '店铺单号', value: '{shopNumber}' },
{ label: '物流单号', value: '{trackingNumber}' },
{ label: '发货数量', value: '{purchaseNumber}' },
{ label: '发货时间', value: '{shipmentTime}' },
{ label: '妥投时间', value: '{properTime}' },
{ label: '商品', value: '{products}' },
{ label: '收货地址', value: '{address}' },
],
},
},
computed: {
html: {
get() {
return this.content
},
set(value) {
this.$emit('change', value)
},
},
toolbarConfig() {
return {
excludeKeys: ['group-video'],
insertKeys: insertKeys(this.isInsert),
}
},
editorConfig() {
const _this = this
return {
placeholder: this.placeholder || '请输入内容...',
MENU_CONF: {
uploadImage: {
allowedFileTypes: [
'jpg',
'jpeg',
'png',
'gif',
'bmp',
],
async customUpload(files, insertFn) {
// JS 语法
// res 即服务端的返回结果
const res = await uploadImg(files)
console.log(res)
const { imagePath } = res
const url = _this.setimgUrl(imagePath, {
w: 640,
})
// 从 res 中找到 url alt href ,然后插入图片
insertFn(url)
},
},
insertSelect: { options: this.insertData },
},
}
},
},
watch: {},
methods: {
onCreated(editor) {
this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
console.log(editor.getConfig())
this.editor.getAllMenuKeys()
},
},
mounted() {
// 模拟 ajax 请求,异步渲染编辑器
},
beforeDestroy() {
const editor = this.editor
if (editor == null) return
editor.destroy() // 组件销毁时,及时销毁编辑器
},
}
</script>
<style scoped>
.editor_toolbar >>> .panel_menu li:hover {
background: #efefef;
}
</style>
class MyDropPanelMenu {
constructor() {
this.title = '插入参数'
// this.iconSvg = '<svg >...</svg>'
this.tag = 'button'
this.showDropPanel = true
}
// 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false
isActive() {
return false
}
// 获取菜单执行时的 value ,用不到则返回空 字符串或 false
getValue() {
return ''
}
// 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
isDisabled() {
return false
}
// 点击菜单时触发的函数
exec() {
// DropPanel menu ,这个函数不用写,空着即可
}
// 定义 DropPanel 内部的 DOM Element
getPanelContentElem(editor) {
const list = document.createElement('ul')
list.classList.add('panel_menu')
const { options } = editor.getMenuConfig('insertSelect')
let html = ''
for (const iterator of options) {
html += `<li style="line-height:28px;cursor: pointer;" data-value="${iterator.value}">${iterator.label}</li>`
}
list.innerHTML = html
list.addEventListener('click', (e) => {
if (e.target.nodeName === 'LI') {
const value = e.target.dataset.value
if (value) {
editor.insertText(value)
editor.insertText(' ')
}
}
})
return list // 返回 DOM Element 类型
// PS:也可以把 $list 缓存下来,这样不用每次重复创建、重复绑定事件,优化性能
}
}
const insetSelect = {
key: 'insertSelect', // 定义 menu key :要保证唯一、不重复(重要)
factory() {
return new MyDropPanelMenu() // 把 `YourMenuClass` 替换为你菜单的 class
},
config: {
options: [],
},
}
export default insetSelect
\ No newline at end of file
......@@ -5,7 +5,7 @@ import store from './store'
import element from '@/common/components/element-ui.js'
import vxeTable from '@/common/components/vxeTable.js'
import './common/style/index.scss'
import { getToken } from '@/utils/auth'
// import { getToken } from '@/utils/auth'
Vue.config.productionTip = false
......@@ -23,12 +23,13 @@ router.afterEach((to, from) => {
})
router.beforeEach((to, form, next) => {
const auth = getToken()
if (!auth && to.path !== '/login') {
next({ path: '/login' })
} else {
next()
}
// const auth = getToken()
// if (!auth && to.path !== '/login') {
// next({ path: '/login' })
// } else {
// next()
// }
next()
})
new Vue({
......
......@@ -4,8 +4,9 @@ import HomeView from '../views/home/HomeView.vue'
import SaasManage from '@/views/saasManage/indexPage.vue'
import LoginPage from '@/views/LoginPage.vue'
import menuPage from '@/views/menu.vue'
export const DEFAULT_DASHBOARD = 'saasManage'
import TaskManage from '@/views/taskManage/index.vue'
import HomePage from '@/views/homePage/index.vue'
export const DEFAULT_DASHBOARD = 'home'
Vue.use(VueRouter)
......@@ -15,16 +16,23 @@ const routes = [
name: 'login',
component: LoginPage,
},
{
path: '/',
name: 'home',
component: HomeView,
redirect: '/saas/manage',
redirect: '/saas/home',
children: [
{
path: '/saas/home',
name: 'home',
component: HomePage,
meta: { title: '首页' },
},
{
path: '/saas/manage',
name: 'saasManage',
meta: { title: 'SaaS管理页面' },
meta: { title: 'ERP管理' },
component: SaasManage,
},
{
......@@ -33,6 +41,18 @@ const routes = [
name: 'saasMenu',
meta: { title: '菜单管理' },
},
{
path: '/saas/taskManage',
component: TaskManage,
name: 'taskManage',
meta: { title: '工单管理' },
},
{
path: '/saas/user',
component: () => import('@/views/system/users.vue'),
name: 'system_user',
meta: { title: '用户管理' },
},
],
},
]
......
......@@ -5,14 +5,14 @@
<h2>登录</h2>
<el-form ref="loginForm" :model="loginForm" class="login-form">
<el-form-item
prop="userName"
prop="account"
:rules="[
{ required: true, message: '请输入用户名' },
]"
>
<el-input
prefix-icon="el-icon-user"
v-model="loginForm.userName"
v-model="loginForm.account"
placeholder="User Name"
clearable
></el-input>
......@@ -61,7 +61,7 @@ export default {
data() {
return {
loginForm: {
userName: '',
account: '',
password: '',
},
showPwd: false,
......@@ -87,7 +87,7 @@ export default {
setToken(res.data.token)
setUser(res.data.saasUser)
this.setUserInfo(res.data.saasUser)
this.$router.push('/saas/manage')
this.$router.push('/saas/home')
}
} catch (e) {
console.error(e)
......
<template>
<div class="home-header">
<page-tags />
<div class="user-area">
<span class="user-name">{{ userInfo && userInfo.userName }}</span>
<el-button type="text" @click="logout"
>退出登录</el-button
>
</div>
</div>
</template>
<script>
import pageTags from './pageTags.vue'
import { logout } from '@/common/api/login'
import { setToken, setUser } from '@/utils/auth'
import { mapState } from 'vuex'
export default {
components: { pageTags },
name: 'HomeHeader',
computed: {
...mapState(['userInfo']),
},
methods: {
async logout() {
try {
await logout()
} catch (e) {
console.error(e)
}
setUser(null)
setToken('')
localStorage.setItem('tags', null)
this.$store.commit('tags/removeAllTags')
this.$router.push('/login')
},
},
computed: {},
methods: {},
}
</script>
<style lang="scss" scoped>
......@@ -48,15 +23,4 @@ export default {
flex: 1;
overflow: auto hidden;
}
.user-area {
display: flex;
align-items: center;
flex-shrink: 0;
padding-right: 16px;
.user-name {
margin-right: 10px;
}
}
</style>
......@@ -39,22 +39,11 @@ export default {
<style lang="scss" scoped>
.home {
height: 100%;
display: flex;
overflow: hidden;
&::v-deep {
.el-menu {
height: 100%;
}
}
}
.nav-menu {
height: 100%;
width: 240px;
}
.right {
height: calc(100% - 60px);
flex: 1;
display: flex;
flex-direction: column;
......@@ -70,7 +59,7 @@ export default {
.content {
flex: 1;
padding: 10px 10px 0px 10px;
padding: 10px;
background-color: #f1f1f1;
}
</style>
......@@ -6,19 +6,17 @@
<el-menu
ref="menu"
router
mode="horizontal"
:default-active="this.$route.path"
class="el-menu-vertical-demo"
text-color="#fff"
style="flex: 1"
background-color="#1565C0"
@click.native="onClickMenus"
active-text-color="#ffd04b"
>
<div
class="menu-list"
v-for="nav in menuList"
:key="nav.id"
>
<template v-for="(nav,index) in menuList">
<el-menu-item
:key="index"
v-if="nav.children.length === 0"
:index="nav.index"
>
......@@ -27,15 +25,15 @@
<span class="label">{{ nav.label }}</span>
</template>
</el-menu-item>
<el-submenu v-else :index="nav.index">
<el-submenu :key="index" v-else :index="nav.index">
<template slot="title">
<i :class="nav.icon"></i>
<span class="label">{{ nav.label }}</span>
</template>
<el-menu-item
:index="subs.index"
v-for="subs in nav.children"
:key="subs.id"
v-for="(subs, index) in nav.children"
:key="index"
>
<template slot="title">
<i :class="subs.icon"></i>
......@@ -45,12 +43,25 @@
>
</el-menu-item>
</el-submenu>
</div>
</template>
</el-menu>
<div class="user-area">
<span class="user-name">{{
userInfo && userInfo.userName
}}</span>
<el-button
type="text"
style="color: #fff"
@click="logout"
>退出登录</el-button
>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { mapGetters, mapState } from 'vuex'
import { logout } from '@/common/api/login'
import { setToken, setUser } from '@/utils/auth'
export default {
name: 'navMenu',
data() {
......@@ -59,12 +70,28 @@ export default {
{
id: 1,
path: '',
label: 'SaaS管理页面',
label: 'ERP管理',
icon: 'el-icon-menu',
index: '/saas/manage',
children: [],
},
{
id: 3,
path: '',
label: 'ERP菜单管理',
icon: 'el-icon-menu',
index: '/saas/menu',
children: [],
},
{
id: 4,
path: '',
label: '工单管理',
icon: 'el-icon-s-order',
index: '/saas/taskManage',
children: [],
},
{
id: 2,
path: '',
label: '系统管理',
......@@ -72,11 +99,19 @@ export default {
index: '/system',
children: [
{
id: 3,
id: 4,
path: '',
label: '菜单管理',
icon: '',
index: '/saas/menu',
label: '用户管理',
icon: 'el-icon-s-order',
index: 'user',
children: [],
},
{
id: 4,
path: '',
label: '角色管理',
icon: 'el-icon-s-order',
index: 'user',
children: [],
},
],
......@@ -86,6 +121,7 @@ export default {
},
computed: {
...mapGetters('tags', ['currentTag']),
...mapState(['userInfo']),
},
watch: {
currentTag(v) {
......@@ -103,13 +139,34 @@ export default {
},
},
methods: {
async logout() {
try {
await logout()
} catch (e) {
console.error(e)
}
setUser(null)
setToken('')
localStorage.setItem('tags', null)
this.$store.commit('tags/removeAllTags')
this.$router.push('/login')
},
onClickMenus() {},
},
}
</script>
<style lang="scss" scoped>
.nav-menu {
display: flex;
height: 60px;
overflow: hidden;
background-color: #1565c0;
&::v-deep {
.el-menu {
border-bottom: none;
}
.el-submenu__title i {
color: #fff;
}
......@@ -120,16 +177,25 @@ export default {
}
.header-logo {
font-size: 20px;
font-size: 22px;
color: #fff;
font-weight: bold;
padding: 12px 20px;
font-style: italic;
border-right: 1px solid #e6e6e6;
background-color: #1565C0;
padding: 14px 20px;
background-color: #1565c0;
}
.label {
font-size: 16px;
}
.user-area {
float: right;
display: flex;
align-items: center;
flex-shrink: 0;
padding-right: 16px;
color: #fff;
.user-name {
margin-right: 10px;
}
}
</style>
<template>
<div>首页</div>
</template>
<script>
export default {
data() {
return {}
},
}
</script>
<style>
</style>
\ No newline at end of file
......@@ -416,8 +416,8 @@ export default {
height: 100%;
display: flex;
flex-direction: column;
padding: 0 20px;
padding-top: 10px;
padding: 10px 20px 0;
overflow: hidden;
}
.table-wrap {
......
......@@ -125,7 +125,7 @@
<el-table-column
label="域名"
prop="domain"
min-width="180"
min-width="160"
header-align="center"
:show-overflow-tooltip="true"
></el-table-column>
......@@ -134,7 +134,7 @@
prop="companyName"
header-align="center"
align="center"
width="160"
width="180"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column
......@@ -142,7 +142,7 @@
prop="headName"
header-align="center"
align="center"
width="140"
width="80"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column
......@@ -150,7 +150,7 @@
prop="contactPhone"
header-align="center"
align="center"
width="140"
width="120"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column
......@@ -158,7 +158,7 @@
prop="packages"
header-align="center"
align="center"
width="140"
width="120"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column
......@@ -166,7 +166,7 @@
prop="charges"
header-align="center"
align="center"
width="140"
width="120"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column
......@@ -174,21 +174,21 @@
prop="dataHost"
header-align="center"
align="left"
width="160"
width="120"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column
label="数据库名称"
prop="databaseName"
header-align="center"
width="160"
width="120"
:show-overflow-tooltip="true"
></el-table-column>
<el-table-column
label="状态"
header-align="center"
align="center"
width="120"
width="80"
:show-overflow-tooltip="true"
>
<template slot-scope="scope">
......@@ -377,9 +377,7 @@
clearable
/>
</el-form-item>
<el-form-item
label="数据库名称"
>
<el-form-item label="数据库名称">
<el-input
style="width: 200px"
:value="`saas_${editForm.databaseName || ''}`"
......@@ -471,7 +469,11 @@
prop="contactPhone"
:rules="[
{ required: true, message: '请输入联系电话' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的电话号码格式', trigger: 'blur' },
{
pattern: /^1[3-9]\d{9}$/,
message: '请输入正确的电话号码格式',
trigger: 'blur',
},
]"
>
<el-input
......@@ -679,7 +681,10 @@ export default {
this.getList()
},
rowClick(row) {
if (this.selection.length === 1 && this.selection[0] === row) {
if (
this.selection.length === 1 &&
this.selection[0] === row
) {
this.selection = []
this.$refs.table.clearSelection()
} else {
......@@ -750,9 +755,4 @@ export default {
flex: 1;
overflow: hidden;
}
.pagination {
text-align: center;
padding-top: 10px;
}
</style>
<template>
<div class="wraper">
<el-form
:inline="true"
size="mini"
@submit.native.prevent
@keyup.enter.capture="search"
>
<el-form-item label="用户名">
<el-input
style="width: 120px"
clearable
v-model="searchForm.employeeName"
placeholder="用户名/姓名"
></el-input>
</el-form-item>
<el-form-item label="功能角色">
<el-select
style="width: 120px"
clearable
filterable
v-model="searchForm.functionRoleId"
placeholder="请选择"
>
<el-option
v-for="item in funcRoleList"
:key="item.value"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据角色">
<el-select
style="width: 120px"
clearable
filterable
v-model="searchForm.dataRoleId"
placeholder="请选择"
>
<el-option
v-for="item in dataRoleList"
:key="item.value"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="启用状态">
<el-select
clearable
:class="{
green: searchForm.enable === '1',
red: searchForm.enable === '0',
}"
v-model="searchForm.enable"
style="width: 120px"
placeholder="请选择"
>
<el-option label="启用" value="1"></el-option>
<el-option label="禁用" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button
native-type="submit"
type="primary"
@click="search()"
icon="el-icon-search"
>
查询
</el-button>
</el-form-item>
<el-form-item>
<el-button type="success" @click="addDialog(1)"
>新增</el-button
>
</el-form-item>
<!-- <el-form-item>
<el-button type="info" @click="addDialog(2)">重置密码</el-button>
</el-form-item>-->
</el-form>
<div class="table_wrap" v-loading="loading">
<table-vue
:sourceData="sourceData"
ref="multipleTable"
:tableColumns="usersTableColumns"
@currentChange="currentTabFn"
:rowClassName="cellClass"
@selectionChange="selectionChange"
></table-vue>
</div>
<div class="pagination">
<el-pagination
layout="sizes, total, prev, pager, next, jumper"
background
:total="total"
:page-size="pageSize"
:current-page="currentPage"
@size-change="sizeChange"
@current-change="onCurrentChange"
>
</el-pagination>
</div>
<!-- 弹出层 -->
<el-dialog
:close-on-click-modal="false"
:title="is_title == 1 ? '新增' : '编辑'"
:visible.sync="dialogVisible"
width="590px"
>
<el-form
label-position="right"
label-width="100px"
size="mini"
:inline="true"
:model="addcurrencyform"
:rules="addrules"
ref="addcurrencyform"
>
<el-form-item
label="登录账号"
prop="account"
required
>
<el-input
style="width: 164px"
v-model="addcurrencyform.account"
placeholder="请输入登录账号"
maxlength="30"
></el-input>
</el-form-item>
<el-form-item label="姓名" prop="" required>
<el-input
style="width: 164px"
v-model="addcurrencyform.realName"
placeholder="请输入登录账号"
maxlength="30"
></el-input>
</el-form-item>
<el-form-item label="是否启用" prop="enable">
<div style="width: 164px" placeholder="请选择">
<el-radio
label="是"
v-model="addcurrencyform.enable"
:value="true"
></el-radio>
<el-radio
label="否"
v-model="addcurrencyform.enable"
:value="false"
></el-radio>
</div>
</el-form-item>
<el-form-item label="功能角色" prop="funcRoleIds">
<el-select
style="width: 164px"
v-model="addcurrencyform.funcRoleIds"
placeholder="请选择角色"
multiple
filterable
>
<el-option
v-for="item in funcRoleList"
:key="item.id"
:label="item.name"
:value="item.id"
>
{{ item.name }}
</el-option>
</el-select>
</el-form-item>
<el-form-item label="数据角色" prop="dataRoleIds">
<el-select
style="width: 164px"
v-model="addcurrencyform.dataRoleIds"
placeholder="请选择角色"
multiple
filterable
>
<el-option
v-for="item in dataRoleList"
:key="item.id"
:label="item.name"
:value="item.id"
>
{{ item.name }}
</el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button
@click="dialogVisible = false"
size="mini"
style="width: 100px"
>
取消
</el-button>
<el-button
type="primary"
@click="addUser()"
size="mini"
style="width: 100px"
>
确认
</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import axios from '../../common/api/axios'
import { mapState } from 'vuex'
import tableVue from '@/common/components/base/tableView.vue'
export default {
name: 'system_users',
components: {
tableVue,
},
data() {
const validatePass = (rule, value, callback) => {
if (this.is_title === 1 && value === '') {
callback(new Error('请输入密码'))
} else {
callback()
}
}
const confirmPass = (rule, value, callback) => {
if (this.is_title === 1 && value === '') {
callback(new Error('确认密码不能为空'))
} else if (
this.is_title === 1 &&
value !== this.addcurrencyform.password
) {
callback(new Error('2次输入的密码不一致'))
} else {
callback()
}
}
return {
is_title: 1,
select: '',
sourceData: [],
searchForm: {
employeeName: '',
enable: '1',
platform: '',
},
dialogVisible: false,
addcurrencyform: {
id: '',
loginName: '',
password: '',
confirmpwd: '',
remark: '',
enable: true,
employeeId: '',
roleId: '',
funcRoleIds: [],
platform: '',
},
addcurrencyform2: null,
formId: null,
addrules: {
password: [
{ validator: validatePass, trigger: 'blur' },
],
confirmpwd: [
{ validator: confirmPass, trigger: 'blur' },
],
loginName: [
{
required: true,
message: '请输入登录账号',
trigger: 'blur',
},
],
employeeName: [
{
required: true,
message: '请选择员工',
trigger: 'change',
},
],
roleId: [
{
required: true,
message: '请选择角色',
trigger: 'change',
},
],
},
roleList: [],
paginationOptions: {
pageSize: 100,
currentPage: 1,
total: 0,
},
details: [],
roleOptions: [],
platforms: [],
total: 0,
pageSize: 100,
currentPage: 1,
loading: false,
}
},
created() {
this.getList(1)
this.addcurrencyform2 = JSON.parse(
JSON.stringify(this.addcurrencyform),
)
// axios.get('sysRole/role_option')
// .then((res) => {
// if (res.code === 200) {
// this.roleOptions = res.data
// }
// })
// .catch((err) => {
// console.log(err)
// })
// axios.get('sysRole/all_list').then((res) => {
// this.roleList = res.data
// })
// axios.get('platform/user/employeePlatformList')
// .then((res) => {
// this.platforms = res.data
// })
// .catch((err) => {
// console.log(err)
// })
},
computed: {
...mapState(['reqMenu', 'employee']),
usersTableColumns() {
return [
{
label: '登录账户',
key: 'account',
width: '',
align: 'left',
render: (item) => (
<span>
<i
class="circle"
style={{
backgroundColor: item.enable
? 'green'
: 'red',
}}
></i>
{item.account}
</span>
),
},
{
label: '姓名',
key: 'realName',
width: '',
},
{ label: '功能角色', key: 'functionNames' },
{ label: '数据角色', key: 'dataNames' },
{
label: '相关操作',
key: '',
fixed: 'right',
width: '',
render: (item) => (
<div>
<span title="编辑" class="icon-view ">
<i
class="el-icon-edit-outline"
style="color:#E6A23C"
onClick={(e) =>
this.addDialog(2, item, e)
}
></i>
</span>
<span title="重置密码" class="icon-view ">
<i
style="color:#67C23A"
class="el-icon-refresh-left"
onClick={(e) => this.resetPwd(e, item)}
></i>
</span>
<span title="删除" class="icon-view ">
<i
style="color:#F56C6C"
class="el-icon-delete"
onClick={(e) => this.deleteSection(item)}
></i>
</span>
</div>
),
},
]
},
funcRoleList() {
if (this.roleList.length > 0) {
return this.roleList.filter(
(item) => item.type === 'FUNCTION_ROLE',
)
}
return []
},
dataRoleList() {
if (this.roleList.length > 0) {
return this.roleList.filter(
(item) => item.type === 'DATA_ROLE',
)
}
return []
},
},
methods: {
onCurrentChange() {},
sizeChange() {},
spentChange(v, item) {
axios
.post('platform/user/update', {
...item,
cost: v,
})
.then(() => {
this.getList()
})
},
cellClass({ row }) {
if (row.authAuditFlag === 1) {
return 'first'
} else {
return ''
}
},
selectionChange(selection) {
if (selection.length > 0) {
this.select = selection
}
},
authorization(item, e) {
e && e.stopPropagation()
},
authorizationDel(item, e) {
e && e.stopPropagation()
this.$confirm('确定删除选中的信息?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {})
.catch(() => {})
},
resetPwd(e, row) {
e && e.stopPropagation()
this.$confirm('确认要重置密码?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
axios
.post('platform/user/resetPassword/' + row.id)
.then((res) => {
this.$alert(
'重置成功\n\r 新密码为:' +
res.data.passWord,
)
})
})
.catch(() => {})
},
enableChange(val, row) {
axios
.post('platform/user/setEnableStatus', {
enable: val,
userId: row.id,
})
.then((res) => {
this.$message.success(res.message)
this.getList()
})
},
bindChange(row) {
axios
.post('platform/user/setBindingStatus', {
bindStatus: !row.bindStatus,
userId: row.id,
})
.then((res) => {
this.$message.success(res.message)
this.getList()
})
},
setempNo(id) {
for (const iterator of this.employee) {
if (iterator.id === id) {
this.addcurrencyform.empNumber =
iterator.empNumber
break
}
}
},
search() {
this.currentPage = 1
this.getList(1)
},
currentTabFn(val) {
if (val.row) {
this.formId = val.row.id
}
},
// 修改新增
async addDialog(i, v = null, e) {
e && e.stopPropagation()
if (i === 2) {
if (v) this.formId = v.id
if (!this.formId) {
return this.$message('请勾选至少一条记录')
}
axios
.get('platform/user/get', {
params: {
id: v.id,
},
})
.then((res) => {
const funcRoleIds = []
const dataRoleIds = []
if (res.data.roleIds) {
const roleIds =
res?.data?.roleIds.split(',') || []
for (const iterator of roleIds) {
const item = this.roleList.find(
(item) => item.id === iterator,
)
if (item) {
if (item.type === 'FUNCTION_ROLE') {
funcRoleIds.push(Number(iterator))
} else {
dataRoleIds.push(Number(iterator))
}
}
}
}
this.addcurrencyform = {
...res.data,
funcRoleIds,
dataRoleIds,
}
this.dialogVisible = true
})
} else {
this.addcurrencyform = JSON.parse(
JSON.stringify(this.addcurrencyform2),
)
this.dialogVisible = true
}
this.is_title = i
this.$nextTick(() => {
this.$refs.addcurrencyform &&
this.$refs.addcurrencyform.clearValidate()
})
},
addUser() {
if (this.is_title === 1) {
this.addSection()
} else {
this.upSection()
}
},
setpaginationOptions(opt) {
for (const key in opt) {
this.paginationOptions[key] = opt[key]
}
this.getList()
},
// 查询
getList() {
this.loading = true
const { pageSize, currentPage } =
this.paginationOptions
axios
.post('platform/user/list_page', {
pageSize,
currentPage,
...this.searchForm,
})
.then((res) => {
this.loading = false
if (res.code === 200) {
this.sourceData = res.data.records
this.paginationOptions.total = res.data.total
} else {
this.$alert(res.message, '错误提示', {
dangerouslyUseHTMLString: true,
})
}
})
},
// 修改
upSection() {
const url = 'platform/user/update'
this.$refs.addcurrencyform.validate((valid) => {
if (valid) {
const data = JSON.parse(
JSON.stringify(this.addcurrencyform),
)
let roleIds =
this.addcurrencyform.funcRoleIds.concat(
this.addcurrencyform.dataRoleIds,
)
roleIds = roleIds.join()
data.roleIds = roleIds
axios.post(url, data).then((res) => {
if (res.code === 200) {
this.dialogVisible = false
this.$message({
message: '修改成功',
type: 'success',
})
this.getList(this.currentPage)
} else {
this.$alert(res.message, '错误提示', {
dangerouslyUseHTMLString: true,
})
}
})
}
})
},
// 新增
addSection() {
const url = 'platform/user/add'
this.$refs.addcurrencyform.validate((valid) => {
if (valid) {
const data = JSON.parse(
JSON.stringify(this.addcurrencyform),
)
let roleIds =
this.addcurrencyform.funcRoleIds.concat(
this.addcurrencyform.dataRoleIds,
)
roleIds = roleIds.join()
data.roleIds = roleIds
axios.post(url, data).then((res) => {
if (res.code === 200) {
this.dialogVisible = false
this.$alert(
'添加成功\n\r 用户密码为:' +
res.data?.passWord || '',
)
this.getList(this.currentPage)
} else {
this.$alert(res.message, '错误提示', {
dangerouslyUseHTMLString: true,
})
}
})
}
})
},
// 删除
deleteSection(v) {
let arr = []
if (v) arr.push(v)
else arr = this.select
const leng = arr.length
if (leng === 0) {
return this.$message('请勾选至少一条记录')
}
let ids = []
ids = arr.map((v) => {
return v.id
})
ids = ids.join()
this.$confirm('确定删除选中的信息?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
axios
.get('platform/user/delete', {
params: {
ids: ids,
},
})
.then((res) => {
if (res.code === 200) {
this.$message({
type: 'success',
message: '删除成功!',
})
this.getList(this.currentPage)
} else {
this.$alert(res.message, '错误提示', {
dangerouslyUseHTMLString: true,
})
}
})
})
.catch(() => {})
},
},
}
</script>
<style scoped>
.wraper {
display: flex;
flex-direction: column;
height: 100%;
}
.table_wrap {
flex: 1;
}
.circle {
display: inline-block;
height: 10px;
width: 10px;
border-radius: 5px;
margin-right: 5px;
}
.my-table >>> .first {
background-color: red !important;
color: #fff !important;
}
</style>
<template>
<el-dialog
:title="isEdit ? '编辑' : '新增'"
:visible.sync="visible"
width="905px"
:close-on-click-modal="false"
:before-close="() => $emit('update:editDialog', false)"
>
<el-form
:inline="true"
size="mini"
:model="editForm"
ref="editForm"
label-width="110px"
>
<el-form-item label="任务编码">
<el-input
style="width: 164px"
v-model="editForm.taskNumber"
disabled
placeholder="系统自动生成"
></el-input>
</el-form-item>
<el-form-item
prop="taskType"
required
label="任务类型"
>
<el-select
style="width: 164px"
filterable
v-model="editForm.taskType"
placeholder="请选择"
@change="getMode"
>
<el-option
v-for="(item, index) in selectOptions.taskType"
:key="index"
:label="item.desc"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
<el-form-item
required
prop="taskModule"
label="任务模块"
>
<el-cascader
v-if="editForm.taskType === 'TECHNOLOGY'"
style="width: 164px"
v-model="editForm.taskModule"
:props="{
emitPath: false,
label: 'name',
value: 'id',
}"
:options="technologyList"
:show-all-levels="false"
></el-cascader>
<el-select
v-else
style="width: 164px"
v-model="editForm.taskModule"
value-key=""
placeholder="请选择"
>
<el-option
v-for="(item, index) in designList"
:key="index"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label="负责人"
prop="taskLeader"
required
>
<el-cascader
style="width: 164px"
v-model="editForm.taskLeader"
:props="{ emitPath: false }"
:options="employee"
:show-all-levels="false"
></el-cascader>
</el-form-item>
<el-form-item
label="验收人"
prop="taskAcceptanceUser"
required
>
<el-cascader
style="width: 164px"
v-model="editForm.taskAcceptanceUser"
:props="{ emitPath: false }"
:options="employee"
:show-all-levels="false"
></el-cascader>
</el-form-item>
<el-form-item label="抄送人">
<el-cascader
style="width: 164px"
v-model="editForm.ccUsers"
:props="{ emitPath: false, multiple: true }"
:options="employee"
:show-all-levels="false"
></el-cascader>
</el-form-item>
<el-form-item
v-if="editForm.taskType === 'TECHNOLOGY'"
label="紧急程度"
prop="emergencyLevel"
required
class="form_item"
>
<el-radio-group v-model="editForm.emergencyLevel">
<el-radio
v-for="(
item, index
) in selectOptions.emergencyLevel"
:key="index"
:label="item.name"
:title="item.desc"
>
<svg
t="1627697200171"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="629"
width="18"
height="18"
>
<path
:fill="setColor(index)"
d="M444.970667 850.090667l151.978666-64.512a85.290667 85.290667 0 0 1-151.978666 64.512z m231.765333-760.746667c89.002667 48.597333 155.818667 111.018667 199.765333 187.178667 43.946667 76.117333 64.64 165.205333 62.250667 266.581333a32 32 0 0 1-64-1.536c2.133333-90.069333-15.872-167.552-53.674667-233.045333-37.802667-65.536-95.957333-119.850667-175.018666-163.029334a32 32 0 1 1 30.72-56.192z m-390.4 188.629333a248.490667 248.490667 0 0 1 324.266667 117.162667l4.181333 8.917333 54.954667 123.392 72.448 62.72c3.968 3.413333 7.381333 7.381333 11.349333 13.824l2.517333 4.906667a53.333333 53.333333 0 0 1-27.178666 70.357333L288.213333 874.24A53.333333 53.333333 0 0 1 213.333333 825.472l-0.042666-99.968-52.992-119.082667A248.405333 248.405333 0 0 1 286.293333 277.973333z m380.288-34.986666c41.258667 22.442667 74.325333 55.210667 98.816 97.621333 24.490667 42.453333 36.309333 87.466667 35.157333 134.442667a32 32 0 1 1-64-1.578667c0.853333-35.029333-7.893333-68.437333-26.581333-100.864-18.688-32.384-43.264-56.661333-74.026667-73.472a32 32 0 0 1 30.634667-56.192z"
p-id="630"
></path>
</svg>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label="重要程度"
v-if="editForm.taskType === 'TECHNOLOGY'"
prop="importanceLevel"
required
class="form_item"
>
<el-radio-group v-model="editForm.importanceLevel">
<el-radio
v-for="(
item, index
) in selectOptions.importanceLevel"
:key="index"
:title="item.desc"
:label="item.name"
>
<svg
t="1627697337193"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="937"
width="18"
height="18"
>
<path
:fill="setColor(index)"
d="M858.1 315l-119 85.9c-15.8 11.4-37.8 7.7-49-8.2L541.6 181.8c-13.9-19.8-43.3-19.7-57.2 0.1L337.8 392.5c-11.1 15.9-33.1 19.7-48.9 8.4l-119.6-85.5c-25.5-18.2-60.2 3.8-54.6 34.6l68.9 380c3 16.6 17.5 28.7 34.3 28.7h598.3c17.1 0 31.7-12.4 34.4-29.3l62.3-380.7c5.1-30.5-29.6-51.9-54.8-33.7zM513.7 620.6c-43.1 0-78-34.9-78-78s34.9-78 78-78 78 34.9 78 78-34.9 78-78 78z"
p-id="938"
></path>
</svg>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label="优先级"
class="form_item"
v-if="editForm.taskType === 'TECHNOLOGY'"
prop="priorityLevel"
required
>
<el-radio-group v-model="editForm.priorityLevel">
<el-radio
v-for="(
item, index
) in selectOptions.priorityLevel"
:key="index"
:label="item.name"
:title="item.desc"
>
<svg
t="1627697676079"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1266"
width="18"
height="18"
>
<path
d="M215.4 160.6H177c-8.9 0-16 7.2-16 16V849c0 8.9 7.2 16 16 16h38.4c8.9 0 16-7.2 16-16V176.7c0.1-8.9-7.1-16.1-16-16.1zM848.1 236c-189 152.5-378-180.6-567.1-28.2-8.8 7.1-16 21.3-16 30.1v430.9c0 8.9 7.2 9 16 1.9 189-152.5 378.1 180.7 567.1 28.2 8.9-7.1 16-21.3 16-30.1V237.9c0.1-8.8-7.1-9-16-1.9z"
:fill="setColor(index)"
p-id="1267"
></path>
</svg>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label="期望完成日期"
prop="expectedCompletionTime"
required
>
<el-date-picker
style="width: 164px"
v-model="editForm.expectedCompletionTime"
value-format="yyyy-MM-dd"
type="date"
:picker-options="pickerOption"
placeholder="选择日期"
></el-date-picker>
</el-form-item>
<br />
<el-form-item label="任务标题">
<el-input
style="width: 732px"
v-model="editForm.taskTitle"
placeholder="任务标题"
></el-input>
</el-form-item>
<br />
<v-editor
height="400px"
ref="wangeditor"
placeholder="任务内容"
v-model="editForm.taskContent"
filename="files"
></v-editor>
</el-form>
<span slot="footer">
<el-button
v-if="isEmpId"
size="mini"
type="warning"
@click="goback"
>
返 回
</el-button>
<el-button
size="mini"
@click="$emit('update:editDialog', false)"
>
取 消
</el-button>
<el-button
size="mini"
type="primary"
@click="onSubmit"
>确 定</el-button
>
</span>
</el-dialog>
</template>
<script>
import Editor from '../../components/wangeditor/index.vue'
import axios from '../../common/api/axios'
import { delChildren } from '../../utils/commonUtil'
export default {
components: {
'v-editor': Editor,
},
data() {
return {
pickerOption: {
disabledDate: (time) => {
return time.getTime() < Date.now() - 8.64e7
},
},
designList: [],
technologyList: [],
}
},
props: {
editForm: {
type: Object,
default: () => ({}),
},
editDialog: {
type: Boolean,
default: false,
},
selectOptions: {
type: Object,
default: () => ({}),
},
isEdit: {
type: Boolean,
default: false,
},
employee: {
type: Array,
default: () => [],
},
},
computed: {
visible: {
get() {
return this.editDialog
},
set(val) {
this.$emit('update:editDialog', val)
},
},
isEmpId() {
const { empId } = this.$route.query
return !!empId
},
taskTypes() {
if (this.selectOptions.taskType) {
return this.selectOptions.taskType
}
return []
},
modeList() {
const { taskType } = this.editForm
if (taskType === 'DESIGN') {
return this.designList
}
if (taskType === 'TECHNOLOGY') {
return this.technologyList
}
return []
},
},
watch: {
editDialog(val) {
if (val) {
this.$nextTick(() => {
this.$refs.editForm &&
this.$refs.editForm.clearValidate()
})
}
},
editForm(newval, old) {
if (newval !== old) {
this.getMode(newval.taskType, true)
}
},
},
methods: {
getMode(code, clear) {
if (!clear) {
this.$set(this.editForm, 'taskModule', '')
}
if (code === 'TECHNOLOGY') {
if (this.technologyList.length === 0) {
axios.get('sysMenu/getAllMenus').then((res) => {
this.technologyList = delChildren(res.data)
const otherList = { id: '-1', name: '其他任务' }
this.technologyList.push(otherList)
})
}
this.$set(this.editForm, 'emergencyLevel', 'URGENT')
this.$set(
this.editForm,
'importanceLevel',
'IMPORTANT',
)
this.$set(this.editForm, 'priorityLevel', 'DURING')
} else {
axios.post('financeTaskSpendNorm/taskPersonalCenter', {
taskType: code,
}).then((res) => {
this.designList = res.data
})
delete this.editForm.emergencyLevel
delete this.editForm.importanceLevel
delete this.editForm.priorityLevel
}
},
goback() {
this.$emit('update:editDialog', false)
this.$router.go(-1)
},
setColor(index) {
if (index === 0) {
return '#F54D66'
}
if (index === 1) {
return '#FDC834'
}
if (index === 2) {
return '#5DE088'
}
},
onSubmit() {
this.$refs.editForm.validate((v) => {
if (v) {
let url = ''
if (this.isEdit) {
url = 'financeTaskManagement/update'
} else {
url = 'financeTaskManagement/add'
}
delete this.editForm.createTime
axios.post(url, this.editForm).then((res) => {
this.$message.success(res.message)
this.$emit('onSubmit')
})
}
})
},
},
}
</script>
<style scoped>
.form_item >>> .el-radio {
margin-right: 13px;
}
.form_item >>> .el-radio svg {
vertical-align: text-bottom;
}
</style>
<!--
* @Description: In User Settings Edit
* @Author: Huidong Che
* @Date: 2020-03-27 16:38:45
* @LastEditors: chd
* @LastEditTime: 2020-11-18 09:25:23
-->
<template>
<div class="wrap" style="padding-top: 0">
<div class="top_wrap">
<el-form
v-show="is_tab == 1"
:model="searchForm"
size="mini"
v-enter-submit="getlist"
:inline="true"
ref="form"
class="search_form"
>
<el-form-item label="">
<el-select
style="width: 80px"
v-model="searchForm.timeProp"
value-key=""
placeholder="时间类型"
clearable
filterable
>
<el-option
label="创建时间"
value="create_time"
></el-option>
<el-option
label="开始时间"
value="start_time"
></el-option>
<el-option
label="预计完成"
value="planned_completion_time"
></el-option>
<el-option
label="实际完成"
value="actual_completion_time"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<choose-time-period
@change="getStatusTree"
v-model="periodTime"
></choose-time-period>
</el-form-item>
<el-form-item label="任务编号">
<el-input
style="width: 120px"
v-model="searchForm.taskNumber"
placeholder="请输入"
clearable
></el-input>
</el-form-item>
<el-form-item label="任务类型">
<el-select
v-model="searchForm.taskType"
style="width: 120px"
value-key=""
placeholder="请选择"
clearable
filterable
>
<el-option
v-for="(type, index) in taskTypes"
:key="index"
:label="type.name"
:value="type.code"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="任务标题">
<el-input
style="width: 120px"
v-model="searchForm.taskTitle"
placeholder="请输入"
clearable
></el-input>
</el-form-item>
<el-form-item label="创建人">
<el-cascader
clearable
style="width: 120px"
v-model="searchForm.taskCreator"
:props="{ emitPath: false }"
:options="deptStaff"
:show-all-levels="false"
></el-cascader>
</el-form-item>
<el-form-item label="负责人">
<el-cascader
clearable
style="width: 120px"
v-model="searchForm.taskLeader"
:props="{ emitPath: false }"
:options="deptStaff"
:show-all-levels="false"
></el-cascader>
</el-form-item>
<el-form-item label>
<el-button
@click="getlist()"
type="primary"
size="mini"
>
查询
</el-button>
</el-form-item>
<el-form-item label>
<el-button
@click="showEdit()"
type="success"
size="mini"
>
新增
</el-button>
</el-form-item>
<el-form-item label v-if="statusCode === '8'">
<el-button
@click="archive()"
type="success"
size="mini"
>
归档
</el-button>
</el-form-item>
<el-form-item label>
<el-checkbox v-model="assignMe">
抄送给我
</el-checkbox>
</el-form-item>
</el-form>
</div>
<div class="page_content">
<div
style="
min-width: 150px;
margin-top: -10px;
padding-top: -10px;
"
>
<status-list
:defauntIndex="defauntIndex"
:statuslist="statusTree"
:isHide="true"
@statusChange="handleNodeClick"
></status-list>
</div>
<div style="flex: 1; overflow: hidden">
<div class="table-wrap">
<table-view
:tableColumns="tableColumns"
:sourceData="sourceData"
:selectionChange="selectionChange"
></table-view>
</div>
<div class="pagination">
<el-pagination
layout="sizes, total, prev, pager, next, jumper"
background
:total="total"
:page-size="pageSize"
:current-page="currentPage"
@size-change="sizeChange"
@current-change="onCurrentChange"
>
</el-pagination>
</div>
</div>
</div>
<!-- 编辑 -->
<edit
:editDialog.sync="editDialog"
@onSubmit="onSubmit"
:selectOptions="selectOptions"
:editForm="editForm"
:taskTypes="taskTypes"
:isEdit="isEdit"
:employee="deptStaff"
ref="edit"
></edit>
<!-- 验收 -->
<el-dialog
:title="statusCode === '8' ? '评价' : '验收'"
:close-on-click-modal="false"
:visible.sync="commentsVisible"
width="30%"
>
<el-form
:model="commentsForm"
size="mini"
ref="commentsForm"
label-width="80px"
>
<el-form-item
label="验收结果"
v-if="statusCode !== '8'"
>
<el-radio
v-model="commentsForm.taskRating"
:label="true"
>
通过
</el-radio>
<el-radio
v-model="commentsForm.taskRating"
:label="false"
>
不通过
</el-radio>
</el-form-item>
<el-form-item
label="评星"
v-if="
statusCode !== '8' && commentsForm.taskRating
"
>
<el-rate
v-model="commentsForm.score"
style="margin-top: 3px"
show-text
:texts="[
'非常糟糕',
'不满意',
'一般',
'满意',
'非常满意',
]"
:colors="['#99A9BF', '#FFCC00', '#FF9900']"
></el-rate>
</el-form-item>
<el-form-item label="评星" v-if="statusCode == '8'">
<el-rate
v-model="commentsForm.score"
style="margin-top: 3px"
show-text
:texts="[
'非常糟糕',
'不满意',
'一般',
'满意',
'非常满意',
]"
:colors="['#99A9BF', '#FFCC00', '#FF9900']"
></el-rate>
</el-form-item>
<el-form-item
label="评价"
v-if="
statusCode !== '8' &&
(commentsForm.score < '4' ||
commentsForm.taskRating == false)
"
>
<el-input
type="textarea"
:rows="4"
placeholder="请输入内容"
v-model="commentsForm.taskEvaluation"
></el-input>
</el-form-item>
<el-form-item
label="描述"
v-if="
statusCode !== '8' && commentsForm.score > '3'
"
>
<el-input
type="textarea"
:rows="4"
placeholder="请输入内容"
v-model="commentsForm.description"
></el-input>
</el-form-item>
</el-form>
<span slot="footer">
<el-button
size="mini"
@click="commentsVisible = false"
>
取 消
</el-button>
<el-button
size="mini"
type="primary"
@click="commentsSubmit"
>
确 定
</el-button>
</span>
</el-dialog>
<el-dialog
title="修改计划"
:visible.sync="updateVisible"
width="360px"
>
<span style="margin-right: 10px">预计开始日期</span>
<el-date-picker
style="width: 200px"
v-model="expectedStartDate"
value-format="yyyy-MM-dd"
type="date"
:picker-options="pickerOption"
placeholder="选择日期"
></el-date-picker>
<span slot="footer">
<el-button @click="updateVisible = false"
>取消</el-button
>
<el-button type="primary" @click="updateTime"
>确定</el-button
>
</span>
</el-dialog>
<!-- 详情 -->
<el-dialog
title="详情"
:visible.sync="detailVisible"
width="900px"
>
<div class="detail_list">
<p class="item">
<span class="label">任务编码</span>
<span class="value">{{ detail.taskNumber }}</span>
</p>
<p class="item">
<span class="label">任务类型</span>
<span class="value">
{{ detail.taskType && detail.taskType.desc }}
</span>
</p>
<p class="item">
<span class="label">任务模块</span>
<span class="value">{{
detail.taskModuleName
}}</span>
</p>
<p class="item">
<span class="label">负责人</span>
<span class="value">{{
detail.taskLeaderName
}}</span>
</p>
<p class="item">
<span class="label">验收人</span>
<span class="value">{{
detail.taskAcceptanceUserName
}}</span>
</p>
<p class="item">
<span class="label">抄送人</span>
<span class="value">{{ detail.ccName }}</span>
</p>
<p class="item">
<span class="label">紧急程度</span>
<span class="value">
<svg
t="1627697200171"
viewBox="0 0 1024 1024"
version="1.1"
style="vertical-align: middle"
xmlns="http://www.w3.org/2000/svg"
p-id="629"
width="18"
height="18"
>
<title>
{{
detail.emergencyLevel
? detail.emergencyLevel.desc
: ''
}}
</title>
<path
:fill="
setIconColor(
detail.emergencyLevel
? detail.emergencyLevel.value
: '',
)
"
d="M444.970667 850.090667l151.978666-64.512a85.290667 85.290667 0 0 1-151.978666 64.512z m231.765333-760.746667c89.002667 48.597333 155.818667 111.018667 199.765333 187.178667 43.946667 76.117333 64.64 165.205333 62.250667 266.581333a32 32 0 0 1-64-1.536c2.133333-90.069333-15.872-167.552-53.674667-233.045333-37.802667-65.536-95.957333-119.850667-175.018666-163.029334a32 32 0 1 1 30.72-56.192z m-390.4 188.629333a248.490667 248.490667 0 0 1 324.266667 117.162667l4.181333 8.917333 54.954667 123.392 72.448 62.72c3.968 3.413333 7.381333 7.381333 11.349333 13.824l2.517333 4.906667a53.333333 53.333333 0 0 1-27.178666 70.357333L288.213333 874.24A53.333333 53.333333 0 0 1 213.333333 825.472l-0.042666-99.968-52.992-119.082667A248.405333 248.405333 0 0 1 286.293333 277.973333z m380.288-34.986666c41.258667 22.442667 74.325333 55.210667 98.816 97.621333 24.490667 42.453333 36.309333 87.466667 35.157333 134.442667a32 32 0 1 1-64-1.578667c0.853333-35.029333-7.893333-68.437333-26.581333-100.864-18.688-32.384-43.264-56.661333-74.026667-73.472a32 32 0 0 1 30.634667-56.192z"
p-id="630"
></path>
</svg>
</span>
</p>
<p class="item">
<span class="label">重要程度</span>
<span class="value">
<svg
t="1627697337193"
style="vertical-align: middle"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="937"
width="18"
height="18"
>
<title>
{{
detail.importanceLevel
? detail.importanceLevel.desc
: ''
}}
</title>
<path
:fill="
setIconColor(
detail.importanceLevel
? detail.importanceLevel.value
: '',
)
"
d="M858.1 315l-119 85.9c-15.8 11.4-37.8 7.7-49-8.2L541.6 181.8c-13.9-19.8-43.3-19.7-57.2 0.1L337.8 392.5c-11.1 15.9-33.1 19.7-48.9 8.4l-119.6-85.5c-25.5-18.2-60.2 3.8-54.6 34.6l68.9 380c3 16.6 17.5 28.7 34.3 28.7h598.3c17.1 0 31.7-12.4 34.4-29.3l62.3-380.7c5.1-30.5-29.6-51.9-54.8-33.7zM513.7 620.6c-43.1 0-78-34.9-78-78s34.9-78 78-78 78 34.9 78 78-34.9 78-78 78z"
p-id="938"
></path>
</svg>
</span>
</p>
<p class="item">
<span class="label">优先级</span>
<span class="value">
<svg
:title="
detail.priorityLevel
? detail.priorityLevel.desc
: ''
"
t="1627697676079"
style="vertical-align: middle"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1266"
width="18"
height="18"
>
<title>
{{
detail.priorityLevel
? detail.priorityLevel.desc
: ''
}}
</title>
<path
d="M215.4 160.6H177c-8.9 0-16 7.2-16 16V849c0 8.9 7.2 16 16 16h38.4c8.9 0 16-7.2 16-16V176.7c0.1-8.9-7.1-16.1-16-16.1zM848.1 236c-189 152.5-378-180.6-567.1-28.2-8.8 7.1-16 21.3-16 30.1v430.9c0 8.9 7.2 9 16 1.9 189-152.5 378.1 180.7 567.1 28.2 8.9-7.1 16-21.3 16-30.1V237.9c0.1-8.8-7.1-9-16-1.9z"
:fill="
setIconColor(
detail.priorityLevel
? detail.priorityLevel.value
: '',
)
"
p-id="1267"
></path>
</svg>
</span>
</p>
<p class="item">
<span class="label">任务状态</span>
<span class="value">
{{
detail.taskStatus && detail.taskStatus.desc
}}
</span>
</p>
<p
class="item"
style="width: 60%"
v-if="detail.completionSteps"
>
<span class="label">完成步骤</span>
<span class="value">{{
detail.completionSteps
}}</span>
</p>
<div
class="split_line"
v-if="detail.taskRating || detail.taskEvaluation"
></div>
<p class="item" v-if="detail.taskRating">
<span class="label">验收结果</span>
<span class="value">
{{
detail.taskRating && detail.taskRating.desc
}}
</span>
</p>
<p
class="item"
style="width: 60%"
v-if="detail.taskEvaluation"
>
<span class="label">验收描述</span>
<span class="value">{{
detail.taskEvaluation
}}</span>
</p>
<div class="split_line"></div>
<p class="item" style="width: 100%">
<span class="label">任务标题</span>
<span class="value" style="width: 732px">{{
detail.taskTitle
}}</span>
</p>
<div
style="
border: 1px solid #ddd;
padding: 5px;
box-shadow: 1px 1px 5px 1px #ddd;
overflow: auto;
"
v-html="detail.taskContent"
@click="fullScreenDisplay"
></div>
<div style="height: 10px"></div>
<p class="item" style="width: 175px">
<span class="label" style="width: auto"
>期望完成日期</span
>
<span class="value">{{
detail.expectedCompletionTime
}}</span>
</p>
<p class="item" style="width: 175px">
<span class="label" style="width: auto"
>计划完成日期</span
>
<span class="value">{{
detail.plannedCompletionTime
}}</span>
</p>
<p class="item">
<span class="label">预计工时(h)</span>
<span class="value">{{ detail.planCycle }}</span>
</p>
<p class="item" style="width: 175px">
<span class="label" style="width: auto"
>任务开始日期</span
>
<span class="value">{{ detail.startTime }}</span>
</p>
<p class="item" style="width: 175px">
<span class="label" style="width: auto"
>实际完成时间</span
>
<span class="value">{{
detail.actualCompletionTime
}}</span>
</p>
<p class="item" style="width: 175px">
<span class="label" style="width: auto"
>实际工时(h)</span
>
<span class="value">{{
detail.actualCycle
}}</span>
</p>
<div
class="split_line"
v-if="detail.logList && detail.logList.length > 0"
></div>
<ul
style="
color: #333;
font-size: 12px;
height: 100%;
overflow: auto;
"
>
<li
class="log_item"
v-for="(item, index) in detail.logList"
:key="index"
>
<div>{{ item.createdTime }}</div>
<div>{{ item.description }}</div>
</li>
</ul>
</div>
<span slot="footer">
<!-- 确认 -->
<span
@click="confimTask(detail)"
class="detail_btn"
style="background: green"
title="确认"
v-if="
this.statusCode !== '-1' &&
detail.taskStatus &&
detail.taskStatus.name === 'HAS_NOT_CONFIRM' &&
(employeeId == detail.taskLeader ||
(detail.taskCompleteUserId &&
detail.taskCompleteUserId.indexOf(
employeeId,
) !== -1))
"
>
<i
class="el-icon-video-play"
style="font-size: 18px"
></i>
&nbsp;确认
</span>
<!-- 开始 -->
<span
@click="startTask(detail)"
class="detail_btn"
style="background: green"
title="开始"
v-if="
this.statusCode !== '-1' &&
detail.taskStatus &&
detail.taskStatus.name === 'HAS_NOT_STARTED' &&
(employeeId == detail.taskLeader ||
(detail.taskCompleteUserId &&
detail.taskCompleteUserId.indexOf(
employeeId,
) !== -1))
"
>
<i class="el-icon-video-play"></i>
&nbsp;开始
</span>
<!-- 终止 -->
<span
class="detail_btn"
style="background: red"
@click="cadence(detail)"
title="终止"
v-if="
employeeId === detail.taskCreator &&
detail.taskStatus &&
(detail.taskStatus.name === 'PROCESSING' ||
detail.taskStatus.name === 'REJECTED_ING')
"
>
<svg
t="1627628609045"
style="
margin-top: 3px;
vertical-align: text-bottom;
"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2698"
width="18"
height="18"
>
<path
d="M509.41569707 75.874304c-238.88418133 0-432.5376 193.65341867-432.5376 432.5376s193.65341867 432.5376 432.5376 432.5376c107.184128 0 205.26312107-38.98627413 280.8283136-103.55234133a435.09787307 435.09787307 0 0 0 17.56255573-15.8564352c10.69438293-8.75342507 19.63567787-18.8809216 19.63567787-33.1808768a37.70395307 37.70395307 0 0 0-9.74411094-25.346048l0.01201494-0.01201494-0.29709654-0.29709653a38.1026304 38.1026304 0 0 0-2.162688-2.162688L285.3830656 230.67579733c61.24776107-49.4665728 139.1722496-79.10741333 224.03263147-79.10741333 197.07876693 0 356.84352 159.76475307 356.84352 356.84352 0 28.71022933-3.39039573 56.6296576-9.79326294 83.37708373l0.0425984 0.01419947a37.91694507 37.91694507 0 0 0-1.1370496 9.22309973c0 20.9027072 16.9443328 37.84704 37.84704 37.84704 17.3146112 0 31.9029248-11.63154773 36.40415574-27.50327466l0.00218453-0.00436907 0.0065536-0.0294912c0.29709653-1.05294507 0.55268693-2.1233664 0.75912533-3.211264a429.9194368 429.9194368 0 0 0 4.554752-21.7546752c4.60281173-25.28815787 7.00689067-51.34199467 7.00689067-77.9583488 0.00109227-238.88418133-193.6523264-432.5376-432.53650773-432.5376z m-356.84352 432.5376c0-84.95213227 29.704192-162.95417173 79.26797653-224.23251627l501.82116693 501.82116694c-61.27834453 49.56378453-139.2934912 79.25377707-224.24562346 79.25377706-197.0798592 0.00109227-356.84352-159.76256853-356.84352-356.84242773z"
fill="#fff"
p-id="2699"
></path>
</svg>
&nbsp;终止
</span>
<!-- 完成 -->
<span
class="detail_btn"
style="background: green"
title="完成"
@click="operation('1', detail)"
v-if="
this.statusCode !== '-1' &&
detail.taskStatus &&
detail.taskStatus.name === 'PROCESSING' &&
(employeeId == detail.taskLeader ||
(detail.taskCompleteUserId &&
detail.taskCompleteUserId.indexOf(
employeeId,
) !== -1))
"
>
<i class="el-icon-circle-check"></i>
完成
</span>
<!-- 验收 -->
<span
class="detail_btn"
@click="operation('2', detail)"
style="background: green"
title="验收"
v-if="
this.statusCode !== '-1' &&
detail.taskStatus &&
detail.taskStatus.name === 'FOR_ACCEPTANCE' &&
employeeId === detail.taskAcceptanceUser
"
>
<i class="el-icon-s-claim"></i>
&nbsp;验收
</span>
<!-- 删除 -->
<span
class="detail_btn"
@click="remove(detail)"
style="background: green"
title="删除"
v-if="
this.statusCode !== '-1' &&
employeeId === detail.taskCreator &&
detail.taskStatus &&
detail.taskStatus.name === 'NOT_YET_ASSIGNED' &&
!detail.reasonForReject
"
>
<i class="el-icon-delete"></i>
&nbsp;删除
</span>
<!-- 指派给 -->
<span
class="detail_btn"
@click="showAssign(detail)"
style="background: green"
title="指派给"
v-if="
this.statusCode !== '-1' &&
detail.taskStatus &&
detail.taskStatus.name === 'NOT_YET_ASSIGNED'
"
>
<svg
t="1629105857363"
style="
vertical-align: middle;
margin-bottom: 3px;
"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1916"
width="18"
height="18"
>
<path
d="M865.83 328.187H545.556l21.133-26.23a34.055 34.055 0 0 0 4.407-7.141c13.433-30.053 25.274-91.855-15.716-132.846-46.246-46.167-127.854-32.84-169.003 22.115L286.08 305.329c-17.894 11.336-74.76 48.874-105.608 86.944l-105.394 6.292c-17.203 1.036-30.636 15.318-30.636 32.574v320.008c0 17.654 14.017 32.096 31.698 32.6l122.439 3.478 270.735 86.998c3.345 1.62 33.397 15.822 68.068 15.822h0.053c40.725 0 72.741-19.592 90.528-56.334a102.65 102.65 0 0 0 7.805-27.212c23.68-0.716 63.343-11.92 82.192-74.732 6.477-23.92 6.902-46.511 1.38-65.758 23.31-12.584 38.654-34.672 42.69-63.583 2.6-18.476 4.034-40.431-2.655-61.139H863.39c57.82 0 116.173-31.83 116.173-102.953-0.002-82.166-73.22-107.944-113.732-110.147z m-3.505 147.845H620.633c-17.999 0-32.6 14.601-32.6 32.627 0 18.025 14.601 32.627 32.6 32.627 54.902 0 69.821 10.327 73.697 14.76 4.832 5.549 5.84 17.787 3.132 37.326-1.009 7.169-2.708 19.194-28.777 19.194-3.982 0-6.903-0.344-7.38-0.424-17.257-2.974-34.406 8.707-37.645 26.362-3.132 17.628 8.496 34.512 26.07 37.857 2.867 0.531 3.982 1.514 4.99 3.16 3.186 5.043 5.15 17.282 0.532 34.3-8.283 27.476-18.69 27.476-22.088 27.476-7.434 0-15.451-3.796-17.575-5.07-12.265-7.7-27.875-6.133-38.76 3.372-10.884 9.478-14.017 25.38-8.017 38.521 0.265 0.558 6.212 13.91-0.053 28.194-6.371 13.141-15.451 18.504-31.327 18.504h-0.053c-19.858 0-39.344-9.186-43.697-10.939l-279.496-90.156c-2.974-0.956-6-1.487-9.132-1.567l-95.413-2.707V461.882l90.156-5.39c10.62-0.637 20.283-6.45 25.858-15.53 15.663-25.592 69.237-64.485 99.289-82.988 3.027-1.885 5.788-4.248 8.017-7.009l104.599-126.5c19.38-25.752 52.405-35.575 71.68-16.354 15.981 16.008 7.008 46.857 3.503 56.838l-60.795 75.397c-7.91 9.769-9.451 23.202-4.035 34.538a32.576 32.576 0 0 0 29.415 18.557l386.43-0.08c8.443 0.61 50.6 5.602 50.6 44.972 0 32.787-31.857 37.699-52.033 37.699z"
fill="#fff"
p-id="1917"
></path>
</svg>
&nbsp;指派
</span>
<!-- 作废 -->
<span
class="detail_btn"
@click="invalid(detail)"
style="background: red"
title="作废"
v-if="
this.statusCode !== '-1' &&
employeeId === detail.taskCreator &&
detail.taskStatus &&
detail.taskStatus.name === 'NOT_YET_ASSIGNED' &&
detail.reasonForReject
"
>
<svg
t="1635313137975"
style="
margin-left: 3px;
margin-top: 3px;
margin-bottom: 1px;
vertical-align: text-top;
"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4954"
width="18"
height="18"
>
<path
d="M526.5 385.2c-17.6 0-32-14.3-32-31.9L493.9 63c0-12.8 7.6-24.4 19.4-29.5 11.8-5.1 25.4-2.6 34.7 6.2l305 290.2c9.5 9 12.5 22.9 7.7 35.1-4.9 12.2-16.6 20.1-29.7 20.1l-304.5 0.1z m31.6-247.6l0.4 183.6 192.5-0.1-192.9-183.5z"
fill="#ffffff"
p-id="4955"
></path>
<path
d="M799.2 353.9v469.3c0 27.9-11 54.2-30.9 74.1s-46.2 30.9-74.1 30.9H200.3c-27.9 0-54.2-11-74.1-30.9s-30.9-46.2-30.9-74.1V200.3c0-27.9 11-54.2 30.9-74.1 19.9-19.9 46.2-30.9 74.1-30.9h322.1v-64H200.3c-93.2 0-169 75.8-169 169v622.9c0 93.2 75.8 169 169 169h493.9c93.2 0 169-75.8 169-169V353.9h-64z"
fill="#ffffff"
p-id="4956"
></path>
<path
d="M624 497.1L314.9 806.2c-12.6 12.6-33.3 12.6-46 0-12.6-12.6-12.6-33.3 0-46L578 451.1c12.6-12.6 33.3-12.6 46 0 12.7 12.7 12.7 33.3 0 46z"
fill="#ffffff"
p-id="4957"
></path>
<path
d="M267 490.2l317 317c12.6 12.6 33.3 12.6 46 0 12.6-12.6 12.6-33.3 0-46l-317-317c-12.6-12.6-33.3-12.6-46 0-12.6 12.7-12.6 33.4 0 46z"
fill="#ffffff"
p-id="4958"
></path>
</svg>
&nbsp;作废
</span>
<!-- 驳回 -->
<span
class="detail_btn"
@click="rejectTask(detail)"
style="background: red"
title="驳回"
v-if="
this.statusCode !== '-1' &&
(employeeId === detail.taskLeader ||
(detail.taskCompleteUserId &&
detail.taskCompleteUserId.indexOf(
employeeId,
) !== -1)) &&
detail.taskStatus &&
(detail.taskStatus.name === 'HAS_NOT_CONFIRM' ||
detail.taskStatus.name === 'HAS_NOT_STARTED')
"
>
<i class="el-icon-s-claim"></i>
&nbsp;驳回
</span>
</span>
</el-dialog>
<!-- 终止 -->
<el-dialog
:close-on-click-modal="false"
:visible.sync="terminationVisible"
width="300px"
>
<el-form>
<el-form-item
label="任务耗时"
label-width="70px"
style="margin-top: 25px"
>
<el-input
v-model="timeConsuming"
placeholder="请输入任务耗时"
size="medium"
></el-input>
</el-form-item>
<el-form-item label="终止原因" label-width="70px">
<el-input
v-model="terminationReason"
type="textarea"
placeholder=""
></el-input>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="terminationVisible = false"
>取消</el-button
>
<el-button type="primary" @click="submitCadence"
>确定</el-button
>
</span>
</el-dialog>
<!-- 预计开始时间 -->
<el-dialog
title="确认"
:close-on-click-modal="false"
:visible.sync="confimVisible"
width="400px"
>
<el-form
:rules="addrules"
label-position="right"
label-width="120px"
:model="expectedStartForm"
ref="expectedStartForm"
>
<el-form-item
label="预计开始日期"
prop="expectedStartDate"
>
<el-date-picker
style="width: 200px"
v-model="expectedStartForm.expectedStartDate"
value-format="yyyy-MM-dd"
:picker-options="pickerOption"
type="date"
placeholder="选择日期"
></el-date-picker>
</el-form-item>
<el-form-item label="预计工时(h)" prop="planCycle">
<el-input
style="width: 200px"
v-model="expectedStartForm.planCycle"
clearable
></el-input>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="confimVisible = false"
>取消</el-button
>
<el-button type="primary" @click="submitConfim"
>确定</el-button
>
</span>
</el-dialog>
<!-- 计划完成日期 -->
<el-dialog
title="计划完成日期"
:close-on-click-modal="false"
:visible.sync="expectedEndVisible"
width="300px"
>
<el-date-picker
style="width: 100%"
v-model="expectedEndTime"
value-format="yyyy-MM-dd"
type="date"
:picker-options="pickerOption"
placeholder="选择日期"
></el-date-picker>
<span slot="footer">
<el-button @click="expectedEndVisible = false"
>取消</el-button
>
<el-button type="primary" @click="submitExpectedEnd"
>确定</el-button
>
</span>
</el-dialog>
<!-- 指派 -->
<el-dialog
title="指派给"
:close-on-click-modal="false"
:visible.sync="assignVisible"
width="300px"
>
<el-cascader
size="small"
v-model="taskLeader"
:props="{ emitPath: false, multiple: true }"
:options="deptStaff"
:show-all-levels="false"
></el-cascader>
<span slot="footer">
<el-button @click="assignVisible = false"
>取消</el-button
>
<el-button type="primary" @click="submitAssign"
>确定</el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
import axios from '../../common/api/axios'
import StatusList from '../../components/base/status-list.vue'
import { emptyArray, getIds } from '../../utils/commonUtil'
import pagination from '../../mixins/pagination'
import Edit from './edit.vue'
import { getDictByCateCode } from '../../utils/api'
import { mapState } from 'vuex'
import ChooseTimePeriod from '../../components/base/chooseTimePeriod.vue'
/* 任务管理 */
import tableView from '@/common/components/base/tableView.vue'
export default {
name: 'task_center',
mixins: [pagination],
components: {
StatusList,
Edit,
ChooseTimePeriod,
tableView,
},
data() {
const userInfo = localStorage.getItem('userinfo')
let employeeId
if (userInfo) {
employeeId = JSON.parse(userInfo).employeeId
}
return {
pickerOption: {
disabledDate: (time) => {
return time.getTime() < Date.now() - 8.64e7
},
},
centerPageOptions: {
pageSize: 100,
currentPage: 1,
total: 0,
},
planPageOptions: {
pageSize: 100,
currentPage: 1,
total: 0,
},
taskLeader: '',
assignVisible: false,
expectedEndVisible: false,
expectedEndTime: '',
periodTime: [],
assignMe: null,
planCycle: '',
terminationVisible: false,
timeConsuming: '',
terminationReason: '',
selections: [],
statusTree: [],
is_tab: '1',
statusCode: '',
commentsForm: {},
completeForm: {},
searchForm: { timeProp: 'create_time' },
expectedStartForm: {
expectedStartDate: '',
planCycle: '',
},
addrules: {
expectedStartDate: [
{
required: true,
message: '请选择预计开始时间',
trigger: 'blur',
},
],
planCycle: [
{
required: true,
message: '请输入预计工时',
trigger: 'blur',
},
],
},
isEdit: false,
sourceData: [],
planData: [],
currentRowId: '',
editDialog: false,
editForm: {},
commentsVisible: false,
selectOptions: {
emergencyLevel: [],
importanceLevel: [],
priorityLevel: [],
taskCompletion: [],
taskRating: [],
taskStatus: [],
taskType: [],
},
detail: {},
detailVisible: false,
updateVisible: false,
employeeId,
iconClasses: [
'icon-rate-face-1',
'icon-rate-face-2',
'icon-rate-face-3',
],
expectedStartDate: '',
confimVisible: false,
defauntIndex: 0,
taskTypes: [],
}
},
mounted() {
getDictByCateCode('taskType').then((res) => {
this.taskTypes = res.data
})
axios.get('financeTaskManagement/enums').then((res) => {
this.selectOptions = res.data
})
let { status, numbers, empId } = this.$route.query
if (status) {
this.statusCode = status
if (status === -1) {
this.assignMe = true
}
}
if (numbers) {
numbers = numbers.split(',')
if (numbers.length === 1) {
this.$set(this.searchForm, 'taskNumber', numbers[0])
}
}
this.getStatusTree()
if (empId) {
this.showEdit(null, () => {
this.$set(
this.editForm,
'taskLeader',
Number(empId),
)
})
}
},
computed: {
...mapState(['deptStaff']),
tableColumns() {
const employeeId = this.employeeId
return [
{
label: '',
type: 'selection',
key: '',
fixed: 'left',
},
{ label: '序号', type: 'index', key: '' },
{ label: '任务编号', key: 'taskNumber', width: 90 },
{
label: '任务模块',
key: 'taskModuleName',
width: 110,
align: 'left',
},
{
label: '任务类型',
key: 'type',
width: 60,
render: (item) => item.taskType?.desc,
},
{
label: '任务标题',
key: 'taskTitle',
width: 120,
align: 'left',
},
{
label: '负责人',
key: 'taskLeaderName',
width: 65,
},
{
label: '执行人',
key: 'taskCompleteUserName',
width: 65,
},
{
label: '验收人',
key: 'taskAcceptanceUserName',
width: 65,
},
{ label: '抄送人', key: 'ccName', width: 80 },
{
label: '创建人',
key: 'taskCreatorName',
width: 65,
},
{
label: '紧急程度',
key: 'emergencyLevel',
width: 60,
render: (item) => (
<svg
t="1627697200171"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="629"
width="18"
style="vertical-align: middle;"
height="18"
>
<title>{item.emergencyLevel?.desc}</title>
<path
fill={this.setIconColor(
item.emergencyLevel?.value,
)}
d="M444.970667 850.090667l151.978666-64.512a85.290667 85.290667 0 0 1-151.978666 64.512z m231.765333-760.746667c89.002667 48.597333 155.818667 111.018667 199.765333 187.178667 43.946667 76.117333 64.64 165.205333 62.250667 266.581333a32 32 0 0 1-64-1.536c2.133333-90.069333-15.872-167.552-53.674667-233.045333-37.802667-65.536-95.957333-119.850667-175.018666-163.029334a32 32 0 1 1 30.72-56.192z m-390.4 188.629333a248.490667 248.490667 0 0 1 324.266667 117.162667l4.181333 8.917333 54.954667 123.392 72.448 62.72c3.968 3.413333 7.381333 7.381333 11.349333 13.824l2.517333 4.906667a53.333333 53.333333 0 0 1-27.178666 70.357333L288.213333 874.24A53.333333 53.333333 0 0 1 213.333333 825.472l-0.042666-99.968-52.992-119.082667A248.405333 248.405333 0 0 1 286.293333 277.973333z m380.288-34.986666c41.258667 22.442667 74.325333 55.210667 98.816 97.621333 24.490667 42.453333 36.309333 87.466667 35.157333 134.442667a32 32 0 1 1-64-1.578667c0.853333-35.029333-7.893333-68.437333-26.581333-100.864-18.688-32.384-43.264-56.661333-74.026667-73.472a32 32 0 0 1 30.634667-56.192z"
p-id="630"
></path>
</svg>
),
},
{
label: '重要程度',
key: 'importanceLevel',
width: 60,
render: (item) => (
<svg
t="1627697337193"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="937"
width="18"
style="vertical-align: middle;"
height="18"
>
<title>{item.importanceLevel?.desc}</title>
<path
fill={this.setIconColor(
item.importanceLevel?.value,
)}
d="M858.1 315l-119 85.9c-15.8 11.4-37.8 7.7-49-8.2L541.6 181.8c-13.9-19.8-43.3-19.7-57.2 0.1L337.8 392.5c-11.1 15.9-33.1 19.7-48.9 8.4l-119.6-85.5c-25.5-18.2-60.2 3.8-54.6 34.6l68.9 380c3 16.6 17.5 28.7 34.3 28.7h598.3c17.1 0 31.7-12.4 34.4-29.3l62.3-380.7c5.1-30.5-29.6-51.9-54.8-33.7zM513.7 620.6c-43.1 0-78-34.9-78-78s34.9-78 78-78 78 34.9 78 78-34.9 78-78 78z"
p-id="938"
></path>
</svg>
),
},
{
label: '优先级',
key: 'priorityLevel',
width: 60,
render: (item) => (
<svg
t="1627697676079"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1266"
width="18"
style="vertical-align: middle;"
height="18"
>
<title>{item.priorityLevel?.desc}</title>
<path
d="M215.4 160.6H177c-8.9 0-16 7.2-16 16V849c0 8.9 7.2 16 16 16h38.4c8.9 0 16-7.2 16-16V176.7c0.1-8.9-7.1-16.1-16-16.1zM848.1 236c-189 152.5-378-180.6-567.1-28.2-8.8 7.1-16 21.3-16 30.1v430.9c0 8.9 7.2 9 16 1.9 189-152.5 378.1 180.7 567.1 28.2 8.9-7.1 16-21.3 16-30.1V237.9c0.1-8.8-7.1-9-16-1.9z"
fill={this.setIconColor(
item.priorityLevel?.value,
)}
p-id="1267"
></path>
</svg>
),
},
{
label: '任务状态',
key: 'taskStatus',
width: 60,
render: (item) => (
<span
style={{
color: this.getStatusColor(
item.taskStatus?.name,
),
}}
>
{item.taskStatus?.desc}
</span>
),
},
{
label: '预计开始时间',
key: 'expectedStartDate',
width: 100,
},
{
label: '期望完成时间',
key: 'expectedCompletionTime',
width: 100,
},
{
label: '计划完成日期',
key: 'plannedCompletionTime',
width: 100,
},
{
label: '预计工时(h)',
key: 'planCycle',
width: 100,
},
{ label: '开始时间', key: 'startTime', width: 100 },
{
label: '实际完成时间',
key: 'actualCompletionTime',
width: 100,
},
{
label: '实际工时(h)',
key: 'actualCycle',
width: 90,
align: 'right',
},
{
label: '创建时间',
key: 'createTime',
width: 130,
},
{
label: '操作',
fixed: 'right',
width: 135,
align: 'left',
render: (item) => (
<span>
{item.taskStatus.name ===
'NOT_YET_ASSIGNED' &&
employeeId === item.taskCreator && (
<span
title="编辑"
class="icon-view icon-edit-view"
>
<i
class="el-icon-edit"
onClick={() => this.showEdit(item)}
></i>
</span>
)}
<span
title="详情"
class="icon-view icon-tools-view"
>
<i
class="el-icon-tickets"
onClick={() => this.showDetail(item)}
></i>
</span>
{this.statusCode !== '-1' &&
employeeId === item.taskCreator &&
item.taskStatus.name ===
'NOT_YET_ASSIGNED' &&
item.reasonForReject && (
<span
title="作废"
class="icon-view icon-del-view"
style="text-align:center;"
onClick={() => this.invalid(item)}
>
<svg
t="1635313137975"
style="margin-left:3px;margin-top:3px"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4954"
width="18"
height="18"
>
<path
d="M526.5 385.2c-17.6 0-32-14.3-32-31.9L493.9 63c0-12.8 7.6-24.4 19.4-29.5 11.8-5.1 25.4-2.6 34.7 6.2l305 290.2c9.5 9 12.5 22.9 7.7 35.1-4.9 12.2-16.6 20.1-29.7 20.1l-304.5 0.1z m31.6-247.6l0.4 183.6 192.5-0.1-192.9-183.5z"
fill="#ffffff"
p-id="4955"
></path>
<path
d="M799.2 353.9v469.3c0 27.9-11 54.2-30.9 74.1s-46.2 30.9-74.1 30.9H200.3c-27.9 0-54.2-11-74.1-30.9s-30.9-46.2-30.9-74.1V200.3c0-27.9 11-54.2 30.9-74.1 19.9-19.9 46.2-30.9 74.1-30.9h322.1v-64H200.3c-93.2 0-169 75.8-169 169v622.9c0 93.2 75.8 169 169 169h493.9c93.2 0 169-75.8 169-169V353.9h-64z"
fill="#ffffff"
p-id="4956"
></path>
<path
d="M624 497.1L314.9 806.2c-12.6 12.6-33.3 12.6-46 0-12.6-12.6-12.6-33.3 0-46L578 451.1c12.6-12.6 33.3-12.6 46 0 12.7 12.7 12.7 33.3 0 46z"
fill="#ffffff"
p-id="4957"
></path>
<path
d="M267 490.2l317 317c12.6 12.6 33.3 12.6 46 0 12.6-12.6 12.6-33.3 0-46l-317-317c-12.6-12.6-33.3-12.6-46 0-12.6 12.7-12.6 33.4 0 46z"
fill="#ffffff"
p-id="4958"
></path>
</svg>
</span>
)}
{this.statusCode !== '-1' &&
item.taskStatus.name ===
'NOT_YET_ASSIGNED' && (
<span
class="icon-view icon-tools-view"
title="指派给"
onClick={() => this.showAssign(item)}
>
<svg
t="1629105857363"
style="vertical-align: middle;margin-bottom: 3px;"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1916"
width="18"
height="18"
>
<path
d="M865.83 328.187H545.556l21.133-26.23a34.055 34.055 0 0 0 4.407-7.141c13.433-30.053 25.274-91.855-15.716-132.846-46.246-46.167-127.854-32.84-169.003 22.115L286.08 305.329c-17.894 11.336-74.76 48.874-105.608 86.944l-105.394 6.292c-17.203 1.036-30.636 15.318-30.636 32.574v320.008c0 17.654 14.017 32.096 31.698 32.6l122.439 3.478 270.735 86.998c3.345 1.62 33.397 15.822 68.068 15.822h0.053c40.725 0 72.741-19.592 90.528-56.334a102.65 102.65 0 0 0 7.805-27.212c23.68-0.716 63.343-11.92 82.192-74.732 6.477-23.92 6.902-46.511 1.38-65.758 23.31-12.584 38.654-34.672 42.69-63.583 2.6-18.476 4.034-40.431-2.655-61.139H863.39c57.82 0 116.173-31.83 116.173-102.953-0.002-82.166-73.22-107.944-113.732-110.147z m-3.505 147.845H620.633c-17.999 0-32.6 14.601-32.6 32.627 0 18.025 14.601 32.627 32.6 32.627 54.902 0 69.821 10.327 73.697 14.76 4.832 5.549 5.84 17.787 3.132 37.326-1.009 7.169-2.708 19.194-28.777 19.194-3.982 0-6.903-0.344-7.38-0.424-17.257-2.974-34.406 8.707-37.645 26.362-3.132 17.628 8.496 34.512 26.07 37.857 2.867 0.531 3.982 1.514 4.99 3.16 3.186 5.043 5.15 17.282 0.532 34.3-8.283 27.476-18.69 27.476-22.088 27.476-7.434 0-15.451-3.796-17.575-5.07-12.265-7.7-27.875-6.133-38.76 3.372-10.884 9.478-14.017 25.38-8.017 38.521 0.265 0.558 6.212 13.91-0.053 28.194-6.371 13.141-15.451 18.504-31.327 18.504h-0.053c-19.858 0-39.344-9.186-43.697-10.939l-279.496-90.156c-2.974-0.956-6-1.487-9.132-1.567l-95.413-2.707V461.882l90.156-5.39c10.62-0.637 20.283-6.45 25.858-15.53 15.663-25.592 69.237-64.485 99.289-82.988 3.027-1.885 5.788-4.248 8.017-7.009l104.599-126.5c19.38-25.752 52.405-35.575 71.68-16.354 15.981 16.008 7.008 46.857 3.503 56.838l-60.795 75.397c-7.91 9.769-9.451 23.202-4.035 34.538a32.576 32.576 0 0 0 29.415 18.557l386.43-0.08c8.443 0.61 50.6 5.602 50.6 44.972 0 32.787-31.857 37.699-52.033 37.699z"
fill="#fff"
p-id="1917"
></path>
</svg>
</span>
)}
{this.statusCode !== '-1' &&
item.taskCompleteUserId &&
item.taskCompleteUserId.indexOf(
employeeId,
) !== -1 &&
item.taskStatus.name ===
'HAS_NOT_CONFIRM' && (
<span
class="icon-view icon-tools-view"
title="确认"
onClick={() => this.confimTask(item)}
>
<i class="el-icon-circle-check"></i>
</span>
)}
{this.statusCode !== '-1' &&
item.taskCompleteUserId &&
item.taskCompleteUserId.indexOf(
employeeId,
) !== -1 &&
(item.taskStatus.name ===
'HAS_NOT_STARTED' ||
item.taskStatus.name === 'REJECTED') && (
<span
title="开始"
class="icon-view icon-tools-view"
>
<i
class="el-icon-video-play"
onClick={() => this.startTask(item)}
></i>
</span>
)}
{this.statusCode !== '-1' &&
item.taskCompleteUserId &&
item.taskCompleteUserId.indexOf(
employeeId,
) !== -1 &&
(item.taskStatus.name ===
'HAS_NOT_CONFIRM' ||
item.taskStatus.name ===
'HAS_NOT_STARTED' ||
item.taskStatus.name === 'REJECTED' ||
item.taskStatus.name ===
'REJECTED_ING') && (
<span
title="驳回"
class="icon-view icon-del-view"
style="text-align:center;"
onClick={() => this.rejectTask(item)}
>
<svg
t="1635312421961"
style="margin-top:3px"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2573"
width="18"
height="18"
>
<path
fill="#fff"
d="M84.80292 468.232171l384.630101-267.805372c0 0 89.454358-47.038316 111.239524 32.574906l0 126.663818c0 0 411.269831 54.283324 374.97009 477.706963 0 0-146.379858-238.867296-374.97009-224.37728l0 137.492444c0 0 1.233084 86.883813-114.861004 47.062875L81.205998 518.906294C81.205998 518.906294 44.906258 493.562069 84.80292 468.232171z"
p-id="2574"
></path>
</svg>
</span>
)}
{this.statusCode !== '-1' &&
employeeId === item.taskCreator &&
(item.taskStatus.name === 'PROCESSING' ||
item.taskStatus.name === 'REJECTED' ||
item.taskStatus.name ===
'REJECTED_ING') && (
<span
title="终止"
class="icon-view icon-del-view"
style="text-align:center;"
onClick={() => this.cadence(item)}
>
<svg
t="1627628609045"
class="icon"
style="margin-top:3px"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2698"
width="18"
height="18"
>
<path
d="M509.41569707 75.874304c-238.88418133 0-432.5376 193.65341867-432.5376 432.5376s193.65341867 432.5376 432.5376 432.5376c107.184128 0 205.26312107-38.98627413 280.8283136-103.55234133a435.09787307 435.09787307 0 0 0 17.56255573-15.8564352c10.69438293-8.75342507 19.63567787-18.8809216 19.63567787-33.1808768a37.70395307 37.70395307 0 0 0-9.74411094-25.346048l0.01201494-0.01201494-0.29709654-0.29709653a38.1026304 38.1026304 0 0 0-2.162688-2.162688L285.3830656 230.67579733c61.24776107-49.4665728 139.1722496-79.10741333 224.03263147-79.10741333 197.07876693 0 356.84352 159.76475307 356.84352 356.84352 0 28.71022933-3.39039573 56.6296576-9.79326294 83.37708373l0.0425984 0.01419947a37.91694507 37.91694507 0 0 0-1.1370496 9.22309973c0 20.9027072 16.9443328 37.84704 37.84704 37.84704 17.3146112 0 31.9029248-11.63154773 36.40415574-27.50327466l0.00218453-0.00436907 0.0065536-0.0294912c0.29709653-1.05294507 0.55268693-2.1233664 0.75912533-3.211264a429.9194368 429.9194368 0 0 0 4.554752-21.7546752c4.60281173-25.28815787 7.00689067-51.34199467 7.00689067-77.9583488 0.00109227-238.88418133-193.6523264-432.5376-432.53650773-432.5376z m-356.84352 432.5376c0-84.95213227 29.704192-162.95417173 79.26797653-224.23251627l501.82116693 501.82116694c-61.27834453 49.56378453-139.2934912 79.25377707-224.24562346 79.25377706-197.0798592 0.00109227-356.84352-159.76256853-356.84352-356.84242773z"
fill="#fff"
p-id="2699"
></path>
</svg>
</span>
)}
{((this.statusCode !== '-1' &&
item.taskStatus.name === 'PROCESSING') ||
item.taskStatus.name ===
'REJECTED_ING') && (
<span
title="完成"
class="icon-view icon-tools-view"
>
<i
class="el-icon-circle-check"
onClick={() =>
this.operation('1', item)
}
></i>
</span>
)}
{this.statusCode !== '-1' &&
item.taskStatus.name === 'FOR_ACCEPTANCE' &&
employeeId === item.taskAcceptanceUser && (
<span
title="验收"
class="icon-view icon-tools-view"
>
<i
class="el-icon-s-claim"
onClick={() =>
this.operation('2', item)
}
></i>
</span>
)}
{employeeId === item.taskCreator &&
item.taskStatus.name ===
'NOT_YET_ASSIGNED' && (
<span
title="删除"
class="icon-view icon-del-view"
>
<i
class="el-icon-delete"
onClick={() => this.remove(item)}
></i>
</span>
)}
{this.statusCode !== '-1' &&
this.statusCode === '8' &&
item.taskStatus.name === 'COMPLETED' &&
employeeId === item.taskAcceptanceUser &&
!item.score && (
<span
title="评价"
class="icon-view icon-tools-view"
>
<i
class="el-icon-chat-dot-square"
onClick={() =>
this.operation('2', item)
}
></i>
</span>
)}
</span>
),
},
]
},
planTableColumns() {
return [
{ label: '任务编号', key: 'taskNumber', width: 90 },
{
label: '任务模块',
key: 'taskModuleName',
width: 120,
align: 'left',
},
{
label: '任务类型',
key: 'type',
width: 120,
render: (item) => item.taskType?.desc,
},
{
label: '任务标题',
key: 'taskTitle',
width: 425,
align: 'left',
},
{
label: '紧急程度',
key: 'emergencyLevel',
width: 90,
render: (item) => (
<svg
t="1627697200171"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="629"
width="18"
style="vertical-align: middle;"
height="18"
>
<title>{item.emergencyLevel?.desc}</title>
<path
fill={this.setIconColor(
item.emergencyLevel?.value,
)}
d="M444.970667 850.090667l151.978666-64.512a85.290667 85.290667 0 0 1-151.978666 64.512z m231.765333-760.746667c89.002667 48.597333 155.818667 111.018667 199.765333 187.178667 43.946667 76.117333 64.64 165.205333 62.250667 266.581333a32 32 0 0 1-64-1.536c2.133333-90.069333-15.872-167.552-53.674667-233.045333-37.802667-65.536-95.957333-119.850667-175.018666-163.029334a32 32 0 1 1 30.72-56.192z m-390.4 188.629333a248.490667 248.490667 0 0 1 324.266667 117.162667l4.181333 8.917333 54.954667 123.392 72.448 62.72c3.968 3.413333 7.381333 7.381333 11.349333 13.824l2.517333 4.906667a53.333333 53.333333 0 0 1-27.178666 70.357333L288.213333 874.24A53.333333 53.333333 0 0 1 213.333333 825.472l-0.042666-99.968-52.992-119.082667A248.405333 248.405333 0 0 1 286.293333 277.973333z m380.288-34.986666c41.258667 22.442667 74.325333 55.210667 98.816 97.621333 24.490667 42.453333 36.309333 87.466667 35.157333 134.442667a32 32 0 1 1-64-1.578667c0.853333-35.029333-7.893333-68.437333-26.581333-100.864-18.688-32.384-43.264-56.661333-74.026667-73.472a32 32 0 0 1 30.634667-56.192z"
p-id="630"
></path>
</svg>
),
},
{
label: '重要程度',
key: 'importanceLevel',
width: 90,
render: (item) => (
<svg
t="1627697337193"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="937"
width="18"
style="vertical-align: middle;"
height="18"
>
<title>{item.importanceLevel?.desc}</title>
<path
fill={this.setIconColor(
item.importanceLevel?.value,
)}
d="M858.1 315l-119 85.9c-15.8 11.4-37.8 7.7-49-8.2L541.6 181.8c-13.9-19.8-43.3-19.7-57.2 0.1L337.8 392.5c-11.1 15.9-33.1 19.7-48.9 8.4l-119.6-85.5c-25.5-18.2-60.2 3.8-54.6 34.6l68.9 380c3 16.6 17.5 28.7 34.3 28.7h598.3c17.1 0 31.7-12.4 34.4-29.3l62.3-380.7c5.1-30.5-29.6-51.9-54.8-33.7zM513.7 620.6c-43.1 0-78-34.9-78-78s34.9-78 78-78 78 34.9 78 78-34.9 78-78 78z"
p-id="938"
></path>
</svg>
),
},
{
label: '优先级',
key: 'priorityLevel',
width: 90,
render: (item) => (
<svg
t="1627697676079"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1266"
width="18"
style="vertical-align: middle;"
height="18"
>
<title>{item.priorityLevel?.desc}</title>
<path
d="M215.4 160.6H177c-8.9 0-16 7.2-16 16V849c0 8.9 7.2 16 16 16h38.4c8.9 0 16-7.2 16-16V176.7c0.1-8.9-7.1-16.1-16-16.1zM848.1 236c-189 152.5-378-180.6-567.1-28.2-8.8 7.1-16 21.3-16 30.1v430.9c0 8.9 7.2 9 16 1.9 189-152.5 378.1 180.7 567.1 28.2 8.9-7.1 16-21.3 16-30.1V237.9c0.1-8.8-7.1-9-16-1.9z"
fill={this.setIconColor(
item.priorityLevel?.value,
)}
p-id="1267"
></path>
</svg>
),
},
{
label: '任务状态',
key: 'taskStatus',
width: 120,
render: (item) => item.taskStatus?.desc,
},
{
label: '预计开始时间',
key: 'expectedStartDate',
width: 100,
},
{
label: '期望完成时间',
key: 'expectedCompletionTime',
width: 100,
},
{
label: '计划完成日期',
key: 'plannedCompletionTime',
width: 100,
},
{
label: '预计工时(h)',
key: 'planCycle',
width: 100,
},
{ label: '开始时间', key: 'startTime', width: 100 },
{
label: '实际完成时间',
key: 'actualCompletionTime',
width: 100,
},
{
label: '操作',
width: 140,
align: 'left',
render: (item) => (
<span>
<span
title="详情"
class="icon-view icon-tools-view"
>
<i
class="el-icon-tickets"
onClick={() => this.showDetail(item)}
></i>
</span>
{(item.taskStatus.name === 'PROCESSING' ||
item.taskStatus.name ===
'REJECTED_ING') && (
<span
title="完成"
class="icon-view icon-tools-view"
>
<i
class="el-icon-circle-check"
onClick={() =>
this.operation('1', item)
}
></i>
</span>
)}
{item.taskStatus.name ===
'HAS_NOT_STARTED' && (
<span
title="修改计划"
class="icon-view icon-tools-view"
>
<i
class="el-icon-edit-outline"
onClick={() => this.updatePlan(item)}
></i>
</span>
)}
</span>
),
},
]
},
},
methods: {
getStatusColor(type) {
if (type === 'NOT_YET_ASSIGNED') {
return '#CCCCCC'
}
if (type === 'HAS_NOT_CONFIRM') {
return '#FF0033'
}
if (type === 'HAS_NOT_STARTED') {
return '#FF9933'
}
if (type === 'PROCESSING' || type === 'REJECTED') {
return '#0066FF'
}
if (
type === 'FOR_ACCEPTANCE' ||
type === 'REJECTED_ING'
) {
return '#00CC33'
}
return '#666'
},
handleClick(v) {
this.is_tab = v
this.getlist()
},
invalid(item) {
this.$confirm('确认作废吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
axios
.post('financeTaskManagement/invalidTask', {
id: item.id,
})
.then((res) => {
this.$message.success(res.message)
this.getStatusTree()
})
.catch(() => {})
})
.catch(() => {})
},
rejectTask(item) {
this.$prompt('请输入驳回原因', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /.+/,
inputErrorMessage: '驳回原因不能为空',
})
.then(({ value }) => {
axios
.post('financeTaskManagement/rejectTask', {
id: item.id,
reasonForReject: value,
})
.then((res) => {
this.$message.success(res.message)
this.getStatusTree()
})
.catch(() => {})
})
.catch(() => {})
},
submitConfim() {
this.$refs.expectedStartForm.validate((v) => {
if (v) {
axios
.get('financeTaskManagement/confirmTask', {
taskId: this.currentRowId,
expectedStartDate:
this.expectedStartForm.expectedStartDate,
planCycle: this.expectedStartForm.planCycle,
})
.then((res) => {
if (res.code === 200) {
this.confimVisible = false
this.getStatusTree()
} else {
this.$confirm(res.message, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
axios
.get(
'financeTaskManagement/confirmContinueTask',
{
taskId: this.currentRowId,
expectedStartDate:
this.expectedStartForm
.expectedStartDate,
planCycle:
this.expectedStartForm
.planCycle,
isContinue: true,
},
)
.then(() => {
this.confimVisible = false
this.getStatusTree()
})
})
.catch(() => {})
}
})
.catch(() => {})
} else {
return false
}
})
},
confimTask(item) {
this.currentRowId = item.id
this.expectedStartForm.expectedStartDate = ''
this.expectedStartForm.planCycle = ''
this.confimVisible = true
},
fullScreenDisplay(e) {
if (e.target.nodeName === 'IMG') {
const uri = e.target.src
console.log(uri)
window.open(uri)
}
},
showAssign(item) {
this.currentRowId = item.id
this.taskLeader = ''
this.assignVisible = true
},
submitAssign() {
axios
.get('financeTaskManagement/assign', {
taskId: this.currentRowId,
taskExecutor: this.taskLeader.join(),
})
.then(() => {
this.assignVisible = false
this.getStatusTree()
})
},
submitExpectedEnd() {
axios
.get('financeTaskManagement/startTask', {
taskId: this.currentRowId,
plannedCompletionTime: this.expectedEndTime,
})
.then((res) => {
this.$message.success(res.message)
this.getStatusTree()
this.expectedEndVisible = false
})
},
setAssign(v, i) {
if (i === 1) {
this.assignMe2 = false
this.assignMe = v ? 'ASSIGN' : null
} else {
this.assignMe1 = false
this.assignMe = v ? true : null
}
this.getStatusTree()
},
setIconColor(index) {
if (index === 3) {
return '#F54D66'
}
if (index === 2) {
return '#FDC834'
}
if (index === 1) {
return '#5DE088'
}
return '#ddd'
},
handleNodeClick({ item }) {
if (item) {
this.statusCode = item.statusCode
this.getlist()
}
},
getStatusTree() {
this.detailVisible = false
axios
.get('financeTaskManagement/getStatusTree', {
copyMe: this.assignMe,
})
.then((res) => {
this.statusTree = res.data
const bool = res.data.some(
(item) =>
item.statusCode === this.statusCode &&
item.quantity === 0,
)
if (bool) {
this.statusCode = null
}
for (let i = 1; i < res.data.length; i++) {
if (
!this.statusCode &&
res.data[i].quantity > 0
) {
this.statusCode = res.data[i].statusCode
this.defauntIndex = i
break
} else if (
this.statusCode === res.data[i].statusCode
) {
this.defauntIndex = i
break
}
}
this.getlist()
})
},
startTask(item) {
if (item.taskStatus.name === 'REJECTED') {
this.$confirm('确认返工?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'success',
}).then(() => {
axios
.get('financeTaskManagement/reStartTask', {
taskId: item.id,
})
.then((res) => {
this.$message.success(res.message)
this.getStatusTree()
this.expectedEndVisible = false
})
})
} else {
this.currentRowId = item.id
this.expectedEndTime = ''
this.expectedEndVisible = true
}
},
async showEdit(v, callback) {
if (v) {
this.isEdit = true
let res = null
try {
res = await axios.get(
'financeTaskManagement/axios.get/' + v.id,
)
} catch (error) {
this.$message.warning(error.message)
return
}
if (res) {
this.editForm = res.data
this.editForm.emergencyLevel =
this.editForm.emergencyLevel?.name
this.editForm.importanceLevel =
this.editForm.importanceLevel?.name
this.editForm.priorityLevel =
this.editForm.priorityLevel?.name
this.editForm.taskType =
this.editForm.taskType.name
this.editDialog = true
}
} else {
this.isEdit = false
this.editForm = {
taskAcceptanceUser: this.employeeId,
}
this.editDialog = true
this.$refs.editForm &&
this.$refs.editForm.resetFields()
}
callback && callback()
},
getlist() {
if (this.is_tab === 1) {
const { pageSize, currentPage } =
this.centerPageOptions
axios
.post('financeTaskManagement/list_page', {
pageSize,
currentPage,
taskStatus: this.statusCode,
copyMe: this.assignMe,
startTime:
this.periodTime && this.periodTime[0],
endTime: this.periodTime && this.periodTime[1],
...this.searchForm,
})
.then((res) => {
this.sourceData = res.data.records
this.centerPageOptions.total = res.data.total
})
} else {
this.planList()
}
},
planList() {
const { pageSize, currentPage } = this.planPageOptions
axios
.get('financeTaskManagement/getFinanceTaskRecord', {
pageSize,
currentPage,
})
.then((res) => {
if (res.code === 200) {
this.planData = res.data.records
this.planPageOptions.total = res.data.total
} else {
this.$alert(res.message, '错误提示', {
dangerouslyUseHTMLString: true,
})
}
})
},
onSubmit() {
this.editDialog = false
this.getStatusTree()
},
operation(type, row) {
this.currentRowId = row.id
this.rework = row.rework
if (type === '1') {
this.$confirm('确认完成?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'success',
})
.then(() => {
axios
.post(
'financeTaskManagement/completeTask/' +
row.id,
)
.then((res) => {
this.$message.success(res.message)
this.getStatusTree()
})
})
.catch((err) => {
console.log(err)
})
} else {
this.commentsVisible = true
this.commentsForm = {}
}
},
commentsSubmit() {
if (
this.rework == null &&
this.commentsForm.score < 4 &&
this.commentsForm.taskRating
) {
this.$alert(
'若您不满意,请选择不通过',
'错误提示',
{
dangerouslyUseHTMLString: true,
},
)
} else {
let url = 'financeTaskManagement/acceptanceTask'
if (this.statusCode === '8') {
url = 'financeTaskManagement/score'
}
axios
.post(url, {
id: this.currentRowId,
rework: this.rework,
...this.commentsForm,
})
.then((res) => {
this.$message.success(res.message)
this.commentsVisible = false
this.getStatusTree()
})
}
},
archive() {
if (emptyArray(this.selections)) return
axios
.get('financeTaskManagement/archive', {
ids: getIds(this.selections, true),
})
.then((res) => {
this.$message.success(res.message)
this.getStatusTree()
})
},
selectionChange(selection) {
this.selections = selection
},
cadence(item) {
this.currentRowId = item.id
this.terminationVisible = true
},
submitCadence() {
axios
.post('financeTaskManagement/terminateTheTask', {
id: this.currentRowId,
reasonForTermination: this.terminationReason,
timeConsuming: this.timeConsuming,
})
.then((res) => {
this.$message.success(res.message)
this.terminationVisible = false
this.getStatusTree()
})
},
remove(item) {
this.$confirm('确定删除选中的信息?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
axios
.post(
'financeTaskManagement/deleteTask/' + item.id,
)
.then((res) => {
this.$message.success(res.message)
this.getStatusTree()
})
})
.catch((err) => {
console.log(err)
})
},
showDetail(item) {
axios
.get('financeTaskManagement/axios.get/' + item.id)
.then((res) => {
this.detail = res.data
this.detailVisible = true
})
},
updatePlan(item) {
axios
.get('financeTaskManagement/axios.get/' + item.id)
.then((res) => {
this.expectedStartDate =
res.data.expectedStartDate
this.planCycle = res.data.planCycle
})
this.updateVisible = true
this.currentRowId = item.id
},
updateTime() {
axios
.get('financeTaskManagement/editTaskTime', {
taskId: this.currentRowId,
expectedStartDate: this.expectedStartDate,
planCycle: this.planCycle,
})
.then((res) => {
this.$message.success(res.message)
this.planList()
this.updateVisible = false
})
},
},
}
</script>
<style scoped>
.top_wrap {
display: flex;
border-bottom: 1px solid #ddd;
}
.tab_bar {
width: 220px;
margin-right: 6px;
box-sizing: border-box;
font-size: 0;
display: flex;
margin-bottom: -1px;
}
.tab_bar li {
flex: 1;
height: 38px;
line-height: 38px;
background: #fff;
cursor: pointer;
user-select: none;
}
.tab_bar span {
display: block;
text-align: center;
color: #333;
font-size: 16px;
}
.tab_bar li + li {
border-left: 1px solid #ddd;
}
.tab_bar li:nth-last-child(1) {
border-right: 1px solid #ddd;
}
.tab_bar li.active {
border-bottom: 1px solid #fff;
}
.tab_bar li.active span {
color: #3366ff;
}
.search_form {
margin-top: 5px;
}
.search_form >>> .el-form-item {
margin-bottom: 5px;
}
.page_content {
display: flex;
height: calc(100% - 40px);
padding: 10px 10px 0 10px;
box-sizing: border-box;
flex-direction: column;
}
.main {
height: 100%;
padding-top: 10px;
display: flex;
flex-direction: column;
}
.detail_list {
max-height: 68vh;
overflow: auto;
}
.detail_list .item {
display: inline-block;
width: 30%;
line-height: 24px;
margin-bottom: 10px;
}
.detail_list .item .label {
display: inline-block;
color: #999;
width: 100px;
text-align: right;
margin-right: 5px;
}
.detail_list .item .value {
color: #222;
}
.form_item >>> .el-radio {
margin-right: 13px;
}
.form_item >>> .el-radio svg {
vertical-align: text-bottom;
}
.detail_btn {
display: inline-block;
font-size: 14px;
border: 1px solid #ddd;
border-radius: 5px;
color: #fff;
padding: 3px 15px;
cursor: pointer;
vertical-align: bottom;
}
.detail_btn + .detail_btn {
margin-left: 10px;
}
.split_line {
height: 1px;
background: #ddd;
margin-bottom: 10px;
}
.log_item {
display: flex;
}
.log_item > div:nth-of-type(1) {
width: 130px;
}
.log_item > div:nth-of-type(2) {
flex: 1;
margin-right: 10px;
}
.table-wrap {
background: #fff;
flex: 1;
overflow: hidden;
}
</style>
......@@ -3,6 +3,6 @@ module.exports = defineConfig({
transpileDependencies: true,
devServer: {
port: 8082,
host: 'wjz.local.cn',
host: '',
},
})
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