oa_app仓库初始化
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<fy-header title="新建协同" back />
|
||||
<view class="body">
|
||||
<view class="field">
|
||||
<text class="lab">标题</text>
|
||||
<view class="box"><input v-model="title" placeholder="请输入任务标题" /></view>
|
||||
</view>
|
||||
<view class="field">
|
||||
<text class="lab">办理人</text>
|
||||
<picker :range="names" @change="pick">
|
||||
<view class="box">{{ assigneeName || '请选择' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="field">
|
||||
<text class="lab">说明</text>
|
||||
<view class="box tall"><textarea v-model="content" /></view>
|
||||
</view>
|
||||
<view class="btn-primary" @click="ok">创建</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FyHeader from '../../components/fy-header.vue'
|
||||
import { store } from '../../utils/store.js'
|
||||
import { asList, toast } from '../../utils/format.js'
|
||||
import { oaGet, oaPost } from '../../utils/api.js'
|
||||
|
||||
export default {
|
||||
components: { FyHeader },
|
||||
data() {
|
||||
return { title: '', content: '', assignees: [], assignee: '', assigneeName: '' }
|
||||
},
|
||||
computed: {
|
||||
names() { return this.assignees.map((a) => a.realName || a.name || a.username) }
|
||||
},
|
||||
onLoad() { this.boot() },
|
||||
methods: {
|
||||
async boot() {
|
||||
try {
|
||||
this.assignees = asList(await oaGet('/work-tasks/assignees', store.token))
|
||||
} catch (_) {
|
||||
this.assignees = Object.values(store.people)
|
||||
}
|
||||
},
|
||||
pick(e) {
|
||||
const a = this.assignees[e.detail.value]
|
||||
this.assignee = a.username || a.id
|
||||
this.assigneeName = a.realName || a.name || a.username
|
||||
},
|
||||
async ok() {
|
||||
if (!this.title.trim()) return toast('请填写标题')
|
||||
if (!this.assignee) return toast('请选择办理人')
|
||||
try {
|
||||
await oaPost('/work-tasks', { title: this.title, content: this.content, assignee: this.assignee }, store.token)
|
||||
toast('已创建', 'success')
|
||||
setTimeout(() => uni.navigateBack(), 400)
|
||||
} catch (e) {
|
||||
toast(e.message || '创建失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.body { padding: 24rpx; }
|
||||
.field { margin-bottom: 20rpx; }
|
||||
.lab { font-size: 24rpx; color: #434655; display: block; margin-bottom: 8rpx; }
|
||||
.box { min-height: 88rpx; background: #fff; border-radius: 16rpx; padding: 20rpx 24rpx; }
|
||||
.box.tall { min-height: 160rpx; }
|
||||
.box input, .box textarea { width: 100%; }
|
||||
</style>
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<fy-header title="协同详情" back />
|
||||
<view v-if="row" class="body">
|
||||
<view class="card">
|
||||
<text class="t">{{ row.title }}</text>
|
||||
<text class="s">发起 {{ row.assignerName || '' }} · 办理 {{ row.assigneeName || '' }}</text>
|
||||
<text class="s">{{ row.content || row.remark || '' }}</text>
|
||||
<text class="chip">{{ row.status === 'done' ? '已办结' : '待办理' }}</text>
|
||||
</view>
|
||||
<view v-if="canDone" class="btn-primary" @click="done">标记已办理</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FyHeader from '../../components/fy-header.vue'
|
||||
import { store } from '../../utils/store.js'
|
||||
import { oaGet, oaPost } from '../../utils/api.js'
|
||||
import { toast } from '../../utils/format.js'
|
||||
|
||||
export default {
|
||||
components: { FyHeader },
|
||||
data() { return { id: '', row: null } },
|
||||
computed: {
|
||||
canDone() {
|
||||
if (!this.row || this.row.status === 'done') return false
|
||||
const me = store.me
|
||||
return me && (String(this.row.assigneeId) === me.id || String(this.row.assignee) === me.username)
|
||||
}
|
||||
},
|
||||
onLoad(q) {
|
||||
this.id = decodeURIComponent(q.id || '')
|
||||
this.load()
|
||||
},
|
||||
methods: {
|
||||
async load() {
|
||||
try {
|
||||
this.row = await oaGet('/work-tasks/' + encodeURIComponent(this.id), store.token)
|
||||
} catch (_) {
|
||||
this.row = { id: this.id, title: '协同任务' }
|
||||
}
|
||||
},
|
||||
async done() {
|
||||
try {
|
||||
await oaPost('/work-tasks/' + encodeURIComponent(this.id) + '/done', {}, store.token)
|
||||
toast('已办结', 'success')
|
||||
this.load()
|
||||
} catch (e) {
|
||||
toast(e.message || '操作失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.body { padding: 24rpx; }
|
||||
.card { padding: 28rpx; margin-bottom: 24rpx; }
|
||||
.t { display: block; font-size: 34rpx; font-weight: 700; }
|
||||
.s { display: block; font-size: 24rpx; color: #737686; margin-top: 8rpx; }
|
||||
.chip { display: inline-block; margin-top: 16rpx; }
|
||||
</style>
|
||||
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<fy-header title="工作协同" back>
|
||||
<template #right>
|
||||
<text v-if="canCreate" class="add" @click="create">+ 新建</text>
|
||||
</template>
|
||||
</fy-header>
|
||||
<view class="sec">待我办理</view>
|
||||
<view v-if="!pending.length" class="empty">暂无</view>
|
||||
<view v-for="t in pending" :key="t.id" class="card item" @click="open(t)">
|
||||
<view class="stripe" />
|
||||
<view class="body">
|
||||
<text class="t">{{ t.title }}</text>
|
||||
<text class="s">{{ t.assignerName || '' }} · {{ t.dueAt || '' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="sec">我发起的</view>
|
||||
<view v-for="t in mine" :key="'m' + t.id" class="card item" @click="open(t)">
|
||||
<view class="body wide">
|
||||
<text class="t">{{ t.title }}</text>
|
||||
<text class="s">{{ t.assigneeName || '' }} · {{ t.status || '' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FyHeader from '../../components/fy-header.vue'
|
||||
import { store } from '../../utils/store.js'
|
||||
import { asList } from '../../utils/format.js'
|
||||
import { oaGet } from '../../utils/api.js'
|
||||
|
||||
export default {
|
||||
components: { FyHeader },
|
||||
data() {
|
||||
return { pending: [], mine: [] }
|
||||
},
|
||||
computed: {
|
||||
canCreate() { return store.can('personal', 'view') }
|
||||
},
|
||||
onShow() { this.load() },
|
||||
methods: {
|
||||
async load() {
|
||||
try {
|
||||
this.pending = asList(await oaGet('/work-tasks?tab=pending', store.token))
|
||||
this.mine = asList(await oaGet('/work-tasks?tab=review', store.token))
|
||||
} catch (_) {}
|
||||
},
|
||||
open(t) {
|
||||
uni.navigateTo({ url: '/pages/coop/detail?id=' + encodeURIComponent(t.id) })
|
||||
},
|
||||
create() {
|
||||
uni.navigateTo({ url: '/pages/coop/create' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sec { padding: 24rpx 24rpx 8rpx; font-size: 28rpx; font-weight: 700; }
|
||||
.item { margin: 12rpx 24rpx; display: flex; overflow: hidden; }
|
||||
.stripe { width: 8rpx; background: #2563eb; }
|
||||
.body { flex: 1; padding: 24rpx; }
|
||||
.body.wide { padding: 24rpx; }
|
||||
.t { display: block; font-size: 28rpx; font-weight: 600; }
|
||||
.s { font-size: 22rpx; color: #737686; }
|
||||
.empty { padding: 24rpx; text-align: center; color: #737686; }
|
||||
.add { color: #2563eb; font-size: 26rpx; font-weight: 700; padding: 8rpx; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user