Commit 674304ee authored by lshan's avatar lshan

ls

parents d4966318 51d6bef7
/**
* @props title:cell标题
* @props titleClass:cell标题样式
* @props titleColor:cell标题文字样式
* @props content:cell内容
* @props contentClass:cell内容样式
* @props type:值 content/input 默认 content,值为input时显示为输入框
* @props value:input value
* @props placeholder:input placeholder
* @props classInput:input样式
* @props dot:boolean,是否显示右侧圆点按钮
* @slot content:内容插槽,替代content显示
* @slot prefix:左侧插槽
* @slot right:右侧插槽
* @event input:type为input时输入事件
* @event click:点击事件
*/
<template> <template>
<div <div
class="mb-px bg-white px-4 rounded" class="mb-px bg-white px-4 rounded"
...@@ -6,7 +23,7 @@ ...@@ -6,7 +23,7 @@
<div v-if="checkIfEmpty(label)" class="text-sm text-text-secondary py-2">{{ label }}</div> <div v-if="checkIfEmpty(label)" class="text-sm text-text-secondary py-2">{{ label }}</div>
<div class="flex py-3 items-center justify-between"> <div class="flex py-3 items-center justify-between">
<slot name="prefix" /> <slot name="prefix" />
<div class="flex justify-between flex-1" :class="contentAlign"> <div class="flex justify-between flex-1" :class="contentClass">
<div v-if="checkIfEmpty(title)" class="title flex-shrink-0 mr-4" :class="getClass">{{ title }}</div> <div v-if="checkIfEmpty(title)" class="title flex-shrink-0 mr-4" :class="getClass">{{ title }}</div>
<!-- 输入框 --> <!-- 输入框 -->
<template v-if="type === 'input'"> <template v-if="type === 'input'">
...@@ -69,7 +86,7 @@ export default Vue.extend({ ...@@ -69,7 +86,7 @@ export default Vue.extend({
default: 'text-right' default: 'text-right'
}, },
titleClass: String, titleClass: String,
contentAlign: { contentClass: {
type: String, type: String,
default: 'items-center' default: 'items-center'
}, },
......
...@@ -5,12 +5,15 @@ ...@@ -5,12 +5,15 @@
<slot name="prefix" /> <slot name="prefix" />
<div class="">{{ title }}</div> <div class="">{{ title }}</div>
</div> </div>
<app-icon <div class="ml-auto flex-shrink-0 flex items-center">
v-if="dot" <slot name="suffix" />
type="png" <app-icon
:path="require('@/assets/icons/dot.png')" v-if="dot"
class-name="h-5 w-1 ml-auto flex-shrink-0" type="png"
/> :path="require('@/assets/icons/dot.png')"
class-name="h-5 w-1"
/>
</div>
</div> </div>
<slot /> <slot />
</div> </div>
......
...@@ -8,7 +8,7 @@ export const okrRoutes: Array<RouteConfig> = [ ...@@ -8,7 +8,7 @@ export const okrRoutes: Array<RouteConfig> = [
{ {
path: '/okr', path: '/okr',
component: () => import('@/layout/home.vue'), component: () => import('@/layout/home.vue'),
redirect: '/okr', redirect: '/okr/okr-home',
children: [ children: [
{ {
path: 'kr-detail', path: 'kr-detail',
...@@ -50,7 +50,31 @@ export const okrRoutes: Array<RouteConfig> = [ ...@@ -50,7 +50,31 @@ export const okrRoutes: Array<RouteConfig> = [
title: '类型' title: '类型'
} }
}, },
{
path: 'okr-home',
name: 'OkrHome',
component: () => import('@/views/okr/okr-home.vue'),
meta: {
title: '我的OKR'
}
},
{
path: 'okr-progress',
name: 'OkrProgress',
component: () => import('@/views/okr/okr-progress.vue'),
meta: {
title: '所有进度'
}
},
{
path: 'key-result',
name: 'KeyResult',
component: () => import('@/views/okr/key-result.vue'),
meta: {
title: '客户数据收集'
}
}
] ]
} }
] ]
\ No newline at end of file
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
<c-cell <c-cell
title-color="text-text-secondary" title-color="text-text-secondary"
title="标签" title="标签"
content-align="items-start" content-class="items-start"
> >
<div slot="content" class="w-full flex flex-wrap items-center"> <div slot="content" class="w-full flex flex-wrap items-center">
<c-tag class="mr-1.5 mb-1.5" label="客户" /> <c-tag class="mr-1.5 mb-1.5" label="客户" />
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
<c-cell <c-cell
title-color="text-text-secondary" title-color="text-text-secondary"
title="电话" title="电话"
content-align="items-start" content-class="items-start"
> >
<div slot="content" class="w-full flex"> <div slot="content" class="w-full flex">
<div class="flex-1">13112345678</div> <div class="flex-1">13112345678</div>
...@@ -111,7 +111,7 @@ ...@@ -111,7 +111,7 @@
<c-cell <c-cell
title-color="text-text-secondary" title-color="text-text-secondary"
title="邮箱" title="邮箱"
content-align="items-start" content-class="items-start"
> >
<div slot="content" class="w-full break-all"> <div slot="content" class="w-full break-all">
123456789@disanbo.com12 123456789@disanbo.com12
...@@ -121,7 +121,7 @@ ...@@ -121,7 +121,7 @@
<c-cell <c-cell
title-color="text-text-secondary" title-color="text-text-secondary"
title="地址" title="地址"
content-align="items-start" content-class="items-start"
> >
<div slot="content" class="w-full break-all"> <div slot="content" class="w-full break-all">
单行高度100,这里是输入的客户地址,没有地址不用显示 单行高度100,这里是输入的客户地址,没有地址不用显示
...@@ -143,7 +143,7 @@ ...@@ -143,7 +143,7 @@
<c-cell <c-cell
title-color="text-text-secondary" title-color="text-text-secondary"
title="地址" title="地址"
content-align="items-start" content-class="items-start"
> >
<div slot="content" class="w-full break-all"> <div slot="content" class="w-full break-all">
杭州复杂美科技有限公司 杭州复杂美科技有限公司
...@@ -153,7 +153,7 @@ ...@@ -153,7 +153,7 @@
<c-cell <c-cell
title-color="text-text-secondary" title-color="text-text-secondary"
title="职位" title="职位"
content-align="items-start" content-class="items-start"
> >
<div slot="content" class="w-full break-all"> <div slot="content" class="w-full break-all">
市场经理 市场经理
...@@ -163,7 +163,7 @@ ...@@ -163,7 +163,7 @@
<c-cell <c-cell
title-color="text-text-secondary" title-color="text-text-secondary"
title="备注" title="备注"
content-align="items-start" content-class="items-start"
> >
<div slot="content" class="w-full break-all"> <div slot="content" class="w-full break-all">
这里是备注备注 这里是备注备注
......
<template>
<div
class="relative"
:style="{width: width + 'px', height: width + 'px'}"
>
<svg viewBox="0 0 100 100">
<path
stroke="#D3DFE6"
stroke-linecap="round"
:d="trackPath"
:stroke-width="relativeStrokeWidth"
fill="none"
:style="trailPathStyle"
/>
<path
:stroke="color"
stroke-linecap="round"
:d="trackPath"
:stroke-width="relativeStrokeWidth"
fill="none"
:style="circlePathStyle"
/>
</svg>
<div class="absolute top-0 left-0 w-full h-full flex items-center justify-center">
<slot name="content">
<div class="text-lg">
{{ percentage + '%'}}
</div>
</slot>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
interface PathStyleObj {
strokeDasharray: string,
strokeDashoffset: string,
[key: string]: string
}
export default Vue.extend({
name: 'Dashboard',
props: {
strokeWidth: {
type: Number,
default: 6
},
width: {
type: Number,
default: 100
},
percentage: {
type: Number,
validator: (val: number) => val >=0 && val <= 100
},
color: {
type: String,
default: '#32B2F7'
}
},
data() {
return {
rate: 0.8,
}
},
computed: {
trackPath(): string {
const radius = this.radius
return `
M 50 50
m 0 ${radius}
a ${radius} ${radius} 0 1 1 0 -${radius * 2}
a ${radius} ${radius} 0 1 1 0 ${radius * 2}
`
},
// 路径相对宽度
relativeStrokeWidth(): string {
const x = this.strokeWidth / this.width * 100
return x.toFixed(1)
},
// 半径
radius(): number {
return parseInt(String(50 - parseFloat(this.relativeStrokeWidth) / 2), 10)
},
// 路径偏移
strokeDashoffset(): string {
const offset = -1 * this.perimeter * (1 - this.rate) / 2
return `${offset}px`
},
// 背景路径样式
trailPathStyle(): PathStyleObj {
return {
strokeDasharray: `${this.perimeter * this.rate}px, ${this.perimeter}px`,
strokeDashoffset: this.strokeDashoffset
}
},
// 填充路径样式
circlePathStyle(): PathStyleObj {
return {
strokeDasharray: `${this.perimeter * this.rate * this.percentage / 100}px, ${this.perimeter}px`,
strokeDashoffset: this.strokeDashoffset,
transition: 'stroke-dasharray 0.6s ease 0s, stroke 0.6s ease'
}
},
// 周长
perimeter(): number {
return 2 * Math.PI * this.radius
}
}
})
</script>
\ No newline at end of file
<template>
<div class="mt-4">
<div class="flex">
<div
v-for="(t, i) in taskList"
:key="i"
class="text-xs text-text-secondary border-r px-4 first:pl-0 last:border-0"
>{{ t.typeName }} {{ t.num }}</div>
</div>
<div class="progress flex items-center mt-3">
<div ref="progressWrapper" class="flex-1 flex bg-text-extreme-light rounded-full h-1.5 overflow-hidden">
<div
v-for="(t, i) in taskList"
:key="i"
class="h-1.5 border-r last:border-none"
:style="getClass(t)"
></div>
</div>
<div class="ml-4 text-xs">{{ percentage }}%</div>
</div>
</div>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
interface Task {
type: 'notStart' | 'inProgress' |'completed' | 'shelved',
typeName: string,
num: number
}
export default Vue.extend({
name: 'Progress',
props: {
taskList: Array as PropType<Array<Task>>
},
data() {
return {
progressWrapperWidth: 0
}
},
computed: {
percentage(): string {
const task = this.taskList.find(task => task.type === 'completed')
if (typeof task !== 'undefined') {
return (task.num / this.totalTaskNum * 100).toFixed(0)
}
return '0'
},
totalTaskNum() {
let total = 0
this.taskList.forEach(task => {
total = total + task.num
})
return total
}
},
mounted() {
const progressWrapper = this.$refs.progressWrapper as HTMLDivElement
if (progressWrapper) {
this.progressWrapperWidth = progressWrapper.getBoundingClientRect().width
}
},
methods: {
getClass(t: Task) {
const width = (t.num / this.totalTaskNum * this.progressWrapperWidth).toFixed(2)
const colorObj = {
notStart: '#E02020',
inProgress: '#F7B500',
completed: '#6DD400',
shelved: ''
}
const obj = {
width: `${width}px`,
background: colorObj[t.type]
}
console.log(obj, 'obj')
return {
width: `${width}px`,
background: colorObj[t.type]
}
}
}
})
</script>
\ No newline at end of file
<template>
<!-- 搜索 -->
<main-page
left-arrow
@click-left="$router.go(-1)"
>
<div class="pt-14 pb-4 px-4">
<group-cell title="工作完成进度">
<c-cell title="所有进度" @click="$router.push('/okr/okr-progress')">
<app-icon
slot="prefix"
icon-name="edit"
class-name="w-4 h-4 mr-2"
/>
</c-cell>
<c-cell title="项目评分">
<app-icon
slot="prefix"
icon-name="edit"
class-name="w-4 h-4 mr-2"
/>
</c-cell>
</group-cell>
<group-cell class="mt-4" title="全部Key Results">
<c-cell title="全部Key Results">
<app-icon
slot="prefix"
icon-name="edit"
class-name="w-4 h-4 mr-2"
/>
</c-cell>
<c-cell title="今日到期Key Results">
<app-icon
slot="prefix"
icon-name="edit"
class-name="w-4 h-4 mr-2"
/>
</c-cell>
</group-cell>
<group-cell class="mt-4" title="全部Objetives">
<app-icon
slot="suffix"
icon-name="plus-black"
class-name="h-5 w-5"
/>
<c-cell title="增强公司内部管理制度">
<div
slot="prefix"
class="text-sm color-tag text-emergency border border-emergency rounded-full py-px px-2.5 mr-4"
>
紧急
</div>
</c-cell>
<c-cell title="部门管理" />
</group-cell>
</div>
</main-page>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
components:{
'main-page': () => import('@/layout/main-page.vue'),
'group-cell': () => import('@/components/common/group-cell.vue'),
'c-cell': () => import('@/components/common/c-cell.vue'),
'app-icon': () => import('@/components/common/Icon.vue')
},
name: 'Search',
data() {
return {}
}
})
</script>
<style lang="less">
</style>
<template>
<!-- 搜索 -->
<main-page
left-arrow
@click-left="$router.go(-1)"
>
<div class="pt-14 pb-4 px-4">
<!-- 统计 -->
<div class="flex items-center justify-center mt-10">
<dashboard
:percentage="percentage"
:strokeWidth="5"
:width="88"
>
<div
slot="content"
class="flex flex-col items-center"
>
<div class="text-xxs text-text-secondary mb-1">完成率</div>
<div class="text-lg">{{ percentage + '%'}}</div>
</div>
</dashboard>
<div class="ml-2">
<div class="flex items-center">
<div class="text-xs text-text-secondary mr-6 w-20 text-right">Objectives</div>
<div class="">3</div>
</div>
<div class="flex items-center">
<div class="text-xs text-text-secondary w-20 mr-6 text-right">Key Results</div>
<div class="">8</div>
</div>
</div>
</div>
<!-- 任务状态/数量 -->
<div class="flex justify-between mt-6">
<div
v-for="(task, index) in taskList"
:key="index"
class="bg-white flex flex-col items-center justify-center px-3 pb-2.5 pt-1.5 rounded"
>
<div :class="taskType(task.type).color">{{ task.num }}</div>
<div class="text-xs text-text-secondary">{{ taskType(task.type).name }}</div>
</div>
</div>
<!-- 列表 -->
<div class="mt-9">
<div class="bg-white px-2.5 py-4 rounded relative">
<app-icon
icon-name="avator"
class-name="w-9 h-9 absolute top-2 right-2"
/>
<!-- 标题 -->
<div class="flex items-center">
<div class="text-sm color-tag text-emergency border border-emergency rounded-full py-px px-2.5 mr-2.5">紧急</div>
<div class="flex-1 pr-9 truncate">{{ task.name }}</div>
</div>
<!-- 时间信息 -->
<div class="flex mt-1.5">
<div class="text-xs bg-text-extreme-light text-text-secondary rounded-sm py-0.5 px-1.5">开始时间:{{ task.startTime }}</div>
<div class="text-xs bg-text-extreme-light text-text-secondary rounded-sm py-0.5 px-1.5 ml-4">截至时间:{{ task.endTime }}</div>
</div>
<!-- 统计 -->
<c-progress :task-list="task.list" />
<!-- <div ref="progressWrapper" class="mt-4">
<div class="flex">
<div
v-for="(t, i) in task.list"
:key="i"
class="text-xs text-text-secondary border-r px-4 first:pl-0 last:border-0"
>{{ t.typeName }} {{ t.num }}</div>
</div>
<div class="progress flex items-center mt-3">
<div class="flex-1 bg-text-extreme-light rounded-full h-1.5 overflow-hidden">
<div ref="progress" class="border bg-color-primary">x</div>
</div>
<div class="ml-4 text-xs">75%</div>
</div>
</div> -->
</div>
</div>
</div>
</main-page>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
components:{
'main-page': () => import('@/layout/main-page.vue'),
// 'group-cell': () => import('@/components/common/group-cell.vue'),
// 'c-cell': () => import('@/components/common/c-cell.vue'),
'app-icon': () => import('@/components/common/Icon.vue'),
'dashboard': () => import('@/views/okr/components/dashboard.vue'),
'c-progress': () => import('@/views/okr/components/progress.vue')
},
name: 'OkrProgress',
data() {
return {
// percentage: 40,
progressWrapperWidth: 0,
taskList: [
{
type: 'notStart',
num: 1
},
{
type: 'inProgress',
num: 2
},
{
type: 'completed',
num: 3
},
{
type: 'shelved',
num: 3
}
],
task: {
name: '增强公司内部管理制度',
tag: 'emergency',
startTime: '04月01日',
endTime: '04月14日',
list: [
{
type: 'completed',
typeName: '已完成',
num: 2
},
{
typeName: '进行中',
type: 'inProgress',
num: 2
},
{
type: 'notStart',
typeName: '未开始',
num: 1
},
{
type: 'shelved',
typeName: '搁置中',
num: 1
}
]
}
}
},
computed: {
percentage(): number {
let total = 0
let completed = 0
this.taskList.forEach(task => {
total = total + task.num
if (task.type === 'completed') {
completed = task.num
}
})
return parseInt((completed / total * 100).toFixed(0))
}
},
methods: {
taskType(type: 'notStart' | 'inProgress' |'completed' | 'shelved') {
const obj = {
notStart: {
name: '未开始',
color: 'text-not-start'
},
inProgress: {
name: '进行中',
color: 'text-tag-orange'
},
completed: {
name: '已完成',
color: 'text-tag-green'
},
shelved: {
name: '已搁置',
color: ''
}
}
return obj[type]
}
}
})
</script>
<style lang="less">
</style>
...@@ -56,7 +56,10 @@ module.exports = { ...@@ -56,7 +56,10 @@ module.exports = {
'field-l': '#FABD60', 'field-l': '#FABD60',
'field-r': '#9AD8E7', 'field-r': '#9AD8E7',
'trip-l': '#F24E72', 'trip-l': '#F24E72',
'trip-r': '#C855B5' 'trip-r': '#C855B5',
// okr
'emergency': '#E14D5C',
'not-start': '#EB8484',
}, },
spacing: { spacing: {
4.5: '1.08rem', 4.5: '1.08rem',
...@@ -949,7 +952,7 @@ module.exports = { ...@@ -949,7 +952,7 @@ module.exports = {
borderOpacity: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'], borderOpacity: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
borderRadius: ['responsive'], borderRadius: ['responsive'],
borderStyle: ['responsive'], borderStyle: ['responsive'],
borderWidth: ['responsive', 'last'], borderWidth: ['responsive', 'last', 'first'],
boxDecorationBreak: ['responsive'], boxDecorationBreak: ['responsive'],
boxShadow: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'], boxShadow: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'],
boxSizing: ['responsive'], boxSizing: ['responsive'],
...@@ -1017,7 +1020,7 @@ module.exports = { ...@@ -1017,7 +1020,7 @@ module.exports = {
outline: ['responsive', 'focus-within', 'focus'], outline: ['responsive', 'focus-within', 'focus'],
overflow: ['responsive'], overflow: ['responsive'],
overscrollBehavior: ['responsive'], overscrollBehavior: ['responsive'],
padding: ['responsive', 'last'], padding: ['responsive', 'last', 'first'],
placeContent: ['responsive'], placeContent: ['responsive'],
placeItems: ['responsive'], placeItems: ['responsive'],
placeSelf: ['responsive'], placeSelf: ['responsive'],
......
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