mirror of
https://shylinux.com/x/operation
synced 2025-07-01 13:14:43 +08:00
opt some
This commit is contained in:
parent
4aa4eb691f
commit
e68128b782
@ -10,71 +10,37 @@ import (
|
||||
type Case struct {
|
||||
Table
|
||||
order string `data:"5"`
|
||||
fields string `data:"title,content,case_status,begin_time,end_time,process_time,finish_time,task_uid,plan_uid,user_uid"`
|
||||
fields string `data:"title,content,status,begin_time,end_time,process_time,finish_time,task_uid,plan_uid,user_uid"`
|
||||
create string `name:"create task_uid* title* content* begin_time:select@date end_time:select@date" role:"worker"`
|
||||
modify string `name:"modify title* content* begin_time*:select@date end_time*:select@date" role:"worker"`
|
||||
}
|
||||
|
||||
func (s Case) Create(m *ice.Message, arg ...string) {
|
||||
s.ValueCreate(m, kit.ArgDef(arg, kit.Simple(model.BEGIN_TIME, m.Time(), model.END_TIME, m.Time("72h"))...)...)
|
||||
s.taskCount(m, "1")
|
||||
s.taskCount(m)
|
||||
s.SendMessage(s.GetCommandUID(m), "", "")
|
||||
}
|
||||
func (s Case) Remove(m *ice.Message, arg ...string) {
|
||||
s.ValueRemove(m, arg...)
|
||||
s.taskCount(m, "-1")
|
||||
s.taskCount(m)
|
||||
}
|
||||
func (s Case) List(m *ice.Message, arg ...string) {
|
||||
user_uid := m.Option(model.USER_UID)
|
||||
s.ValueList(m, arg).Table(func(value ice.Maps) {
|
||||
button := []ice.Any{}
|
||||
switch CaseStatus(kit.Int(value[model.CASE_STATUS])) {
|
||||
case CaseCreate:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Process)
|
||||
}
|
||||
case CaseProcess:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Finish)
|
||||
}
|
||||
case CaseFinish:
|
||||
kit.If(len(arg) == 2, func() { s.DoneMessage(m) })
|
||||
}
|
||||
m.PushButton(button...)
|
||||
}).Display("")
|
||||
s.Orders(m, model.STATUS, s.Desc(model.CREATED_AT))
|
||||
s.ValueList(m, arg).Table(func(value ice.Maps) { s.PushTaskButton(m, value, user_uid) }).Display("")
|
||||
m.RenameAppend(model.STATUS, model.CASE_STATUS)
|
||||
s.SelectJoinPlan(m)
|
||||
s.StatusCount(m, arg...)
|
||||
}
|
||||
func (s Case) Process(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, CaseCreate, CaseProcess)
|
||||
s.changeStatus(m, TaskCreate, TaskProcess)
|
||||
}
|
||||
func (s Case) Finish(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, CaseProcess, CaseFinish)
|
||||
s.changeStatus(m, TaskProcess, TaskFinish)
|
||||
}
|
||||
|
||||
func init() { ice.TeamCtxCmd(Case{}) }
|
||||
|
||||
func (s Case) changeStatus(m *ice.Message, from, to CaseStatus) {
|
||||
func (s Case) changeStatus(m *ice.Message, from, to TaskStatus) {
|
||||
s.ChangeStatus(m, int(from), int(to), m.ActionKey()+"_time", m.Time())
|
||||
}
|
||||
func (s Case) taskCount(m *ice.Message, value string) {
|
||||
if m.IsErr() || m.Option(model.TASK_UID) == "" {
|
||||
return
|
||||
}
|
||||
m.Cmd(Task{}, s.AddCount, model.CASE_COUNT, value, m.Option(model.TASK_UID))
|
||||
}
|
||||
|
||||
type CaseStatus int
|
||||
|
||||
const (
|
||||
CaseCreate CaseStatus = iota
|
||||
CaseProcess
|
||||
CaseFinish
|
||||
)
|
||||
|
||||
var CaseStatusList = map[CaseStatus]string{
|
||||
CaseCreate: "create",
|
||||
CaseProcess: "process",
|
||||
CaseFinish: "finish",
|
||||
}
|
||||
|
||||
func (s CaseStatus) String() string { return CaseStatusList[s] }
|
||||
|
@ -2,7 +2,7 @@ Volcanos(chat.ONIMPORT, {
|
||||
_init: function(can, msg) {
|
||||
can.onimport.myView(can, msg, function(value) { return [
|
||||
{view: html.TITLE, list: [value.title, can.onimport.textView(can, value)]},
|
||||
{view: html.STATUS, list: [(value.process_time||value.begin_time).split(" ")[0], "计划:", value.plan_title]},
|
||||
{view: html.STATUS, list: [can.onimport.beginTime(can, value), can.onimport.unitView(can, value, "plan_title")]},
|
||||
{view: html.OUTPUT, list: [value.content]}, can.onimport.titleAction(can, value),
|
||||
] })
|
||||
},
|
||||
|
@ -1,7 +1,10 @@
|
||||
package production
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"shylinux.com/x/ice"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
|
||||
"shylinux.com/x/operation/src/operation"
|
||||
@ -11,8 +14,14 @@ import (
|
||||
type Table struct {
|
||||
operation.Table
|
||||
remove string `name:"remove" role:"worker"`
|
||||
reject string `name:"reject" role:"leader"`
|
||||
approve string `name:"approve" role:"leader"`
|
||||
process string `name:"process" role:"worker"`
|
||||
finish string `name:"finish" role:"worker"`
|
||||
submit string `name:"submit link" role:"worker"`
|
||||
reback string `name:"reback" role:"leader"`
|
||||
finish string `name:"finish" role:"leader"`
|
||||
payfor string `name:"payfor price* title* content"`
|
||||
discuss string `name:"discuss type* title* content date* time* link*"`
|
||||
list string `name:"list story_uid uid auto" role:"void"`
|
||||
}
|
||||
|
||||
@ -26,14 +35,36 @@ func (s Table) Inputs(m *ice.Message, arg ...string) {
|
||||
s.InputsUID(m, Plan{}, arg...)
|
||||
case model.ISSUE_UID:
|
||||
s.InputsUID(m, Issue{}, arg...)
|
||||
case model.TASK_UID:
|
||||
s.InputsUID(m, Task{}, arg...)
|
||||
case model.ISSUE_TYPE:
|
||||
s.InputsList(m, IssueTypeList, arg...)
|
||||
case model.MEET_TYPE:
|
||||
s.InputsList(m, MeetTypeList, arg...)
|
||||
case model.TASK_UID:
|
||||
s.InputsUID(m, Task{}, arg...)
|
||||
case model.LEVEL:
|
||||
s.InputsList(m, LevelList, arg...)
|
||||
case model.FROM_USER_UID, model.TO_USER_UID:
|
||||
m.Cmdy("member", m.Option(model.STORY_UID)).Cut(model.USER_UID, model.USER_NAME, model.USER_AVATAR)
|
||||
m.RenameAppend(model.USER_UID, arg[0], model.NAME, model.USER_NAME, model.USER_AVATAR, mdb.ICONS)
|
||||
m.DisplayInputKeyNameIconTitle()
|
||||
default:
|
||||
s.Table.Inputs(m, arg...)
|
||||
switch m.Option("action") {
|
||||
case "discuss":
|
||||
switch arg[0] {
|
||||
case "type":
|
||||
m.Push(arg[0], "需求沟通", "需求评审", "项目验收")
|
||||
case "date":
|
||||
for i := 1; i < 10; i++ {
|
||||
m.Push(arg[0], strings.Split(m.Time(kit.Format("%dh", i*24)), " ")[0])
|
||||
}
|
||||
case "time":
|
||||
for i := 18; i < 48; i++ {
|
||||
m.Push(arg[0], kit.Format("%02d:%s", i/2, kit.Select("30", "00", i%2 == 0)))
|
||||
}
|
||||
}
|
||||
default:
|
||||
s.Table.Inputs(m, arg...)
|
||||
}
|
||||
}
|
||||
}
|
||||
func (s Table) RewriteAppend(m *ice.Message, arg ...string) *ice.Message {
|
||||
@ -47,14 +78,12 @@ func (s Table) RewriteAppend(m *ice.Message, arg ...string) *ice.Message {
|
||||
value = PlanStatus(kit.Int(value)).String()
|
||||
case model.ISSUE_TYPE:
|
||||
value = IssueType(kit.Int(value)).String()
|
||||
case model.ISSUE_STATUS:
|
||||
case model.MEET_TYPE:
|
||||
value = MeetType(kit.Int(value)).String()
|
||||
case model.ISSUE_STATUS, model.DESIGN_STATUS, model.STATUS:
|
||||
value = IssueStatus(kit.Int(value)).String()
|
||||
case model.DESIGN_STATUS:
|
||||
value = DesignStatus(kit.Int(value)).String()
|
||||
case model.TASK_STATUS:
|
||||
case model.TASK_STATUS, model.CASE_STATUS:
|
||||
value = TaskStatus(kit.Int(value)).String()
|
||||
case model.CASE_STATUS:
|
||||
value = CaseStatus(kit.Int(value)).String()
|
||||
case model.LEVEL:
|
||||
value = Level(kit.Int(value)).String()
|
||||
}
|
||||
@ -62,13 +91,155 @@ func (s Table) RewriteAppend(m *ice.Message, arg ...string) *ice.Message {
|
||||
})
|
||||
return s.Table.RewriteAppend(m)
|
||||
}
|
||||
func (s Table) PushIssueButton(m *ice.Message, value ice.Maps, user_uid string, arg ...ice.Any) {
|
||||
button := []ice.Any{}
|
||||
isLeader, isWorker := s.IsLeader(m), s.IsWorker(m)
|
||||
switch IssueStatus(kit.Int(value[model.STATUS])) {
|
||||
case IssueCreate:
|
||||
if isLeader {
|
||||
button = append(button, s.Discuss)
|
||||
button = append(button, s.Approve, s.Reject)
|
||||
}
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Modify, s.Remove)
|
||||
}
|
||||
case IssueApproved:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Process)
|
||||
}
|
||||
case IssueProcess:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Submit)
|
||||
}
|
||||
if isLeader && kit.Int(value[model.PRICE]) > 0 {
|
||||
button = append(button, s.Payfor)
|
||||
}
|
||||
case IssueSubmit:
|
||||
if isLeader {
|
||||
button = append(button, s.Discuss)
|
||||
button = append(button, s.Reback, s.Finish)
|
||||
}
|
||||
case IssueFinish:
|
||||
if isWorker {
|
||||
button = append(button, arg...)
|
||||
}
|
||||
if isLeader && kit.Int(value[model.PRICE]) > 0 {
|
||||
button = append(button, s.Payfor)
|
||||
button = append(button, s.Discuss)
|
||||
}
|
||||
kit.If(len(arg) == 2 && value[model.PRICE] == "0", func() { s.DoneMessage(m) })
|
||||
}
|
||||
m.PushButton(button...)
|
||||
}
|
||||
func (s Table) PushTaskButton(m *ice.Message, value ice.Maps, user_uid string, arg ...ice.Any) {
|
||||
button := []ice.Any{}
|
||||
isLeader, isWorker := s.IsLeader(m), s.IsWorker(m)
|
||||
switch TaskStatus(kit.Int(value[model.STATUS])) {
|
||||
case TaskCreate:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Process, s.Modify, s.Remove)
|
||||
}
|
||||
if isLeader {
|
||||
}
|
||||
case TaskProcess:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Finish)
|
||||
}
|
||||
if isWorker {
|
||||
button = append(button, arg...)
|
||||
}
|
||||
if isLeader && kit.Int(value[model.PRICE]) > 0 {
|
||||
button = append(button, s.Payfor)
|
||||
}
|
||||
case TaskFinish:
|
||||
if isLeader && kit.Int(value[model.PRICE]) > 0 {
|
||||
button = append(button, s.Payfor)
|
||||
}
|
||||
kit.If(len(arg) == 2, func() { s.DoneMessage(m) })
|
||||
}
|
||||
m.PushButton(button...)
|
||||
}
|
||||
func (s Table) SelectJoinPlan(m *ice.Message, arg ...string) {
|
||||
s.SelectJoin(m, Plan{}, model.TITLE)
|
||||
}
|
||||
func (s Table) StatusCount(m *ice.Message, arg ...string) {
|
||||
if m.Length() > 0 && len(arg) < 2 {
|
||||
msg := m.Spawn()
|
||||
s.Fields(msg, "status, count(*) AS count").Groups(msg, model.STATUS).Orders(msg, model.STATUS)
|
||||
s.Select(msg, model.STORY_UID, arg[0]).Table(func(value ice.Maps) {
|
||||
switch status := kit.Int(value[model.STATUS]); m.CommandKey() {
|
||||
case "plan":
|
||||
m.Echo(PlanStatus(status).String()).Echo(": ")
|
||||
case "issue", "design":
|
||||
m.Echo(IssueStatus(status).String()).Echo(": ")
|
||||
case "task", "case":
|
||||
m.Echo(TaskStatus(status).String()).Echo(": ")
|
||||
}
|
||||
m.Echo(value[model.COUNT]).Echo("\n")
|
||||
})
|
||||
}
|
||||
}
|
||||
func (s Table) Reject(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, IssueCreate, IssueRejected)
|
||||
}
|
||||
func (s Table) Approve(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, IssueCreate, IssueApproved)
|
||||
}
|
||||
func (s Table) Process(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, IssueApproved, IssueProcess)
|
||||
}
|
||||
func (s Table) Submit(m *ice.Message, arg ...string) {
|
||||
s.ChangeStatus(m, int(IssueProcess), int(IssueSubmit), arg...)
|
||||
}
|
||||
func (s Table) Reback(m *ice.Message, arg ...string) {
|
||||
s.ChangeStatus(m, int(IssueSubmit), int(IssueProcess))
|
||||
}
|
||||
func (s Table) Finish(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, IssueSubmit, IssueFinish)
|
||||
}
|
||||
func (s Table) Payfor(m *ice.Message, arg ...string) {
|
||||
}
|
||||
func (s Table) Discuss(m *ice.Message, arg ...string) {
|
||||
m.Cmd(meet{}, s.Create, arg)
|
||||
}
|
||||
func (s Issue) Payfor(m *ice.Message, arg ...string) {
|
||||
msg := s.Select(m, model.UID, m.Option(model.UID))
|
||||
m.Cmdy(deal{}, s.Create, model.FROM_USER_UID, m.Option(model.USER_UID), model.TO_USER_UID, msg.Append(model.USER_UID),
|
||||
model.PLAN_UID, msg.Append(model.UID), model.ISSUE_UID, m.Option(model.UID), arg)
|
||||
}
|
||||
func (s Issue) Discuss(m *ice.Message, arg ...string) {
|
||||
m.Cmd(meet{}, s.Create, model.ISSUE_UID, m.Option(model.UID), arg, m.OptionSimple(model.PLAN_UID))
|
||||
}
|
||||
func (s Table) OtherCreate(m *ice.Message, target ice.Any, arg ...string) {
|
||||
kit.If(m.CommandKey() != "plan", func() { arg = append(arg, m.OptionSimple(model.PLAN_UID)...) })
|
||||
m.Cmdy(target, s.Create, m.CommandKey()+"_uid", m.Option(model.UID), arg)
|
||||
kit.If(!m.IsErr(), func() { m.ProcessField(target, []string{m.Option(model.STORY_UID), m.Result()}) })
|
||||
}
|
||||
func (s Table) OtherList(m *ice.Message, target ice.Any, arg ...string) *ice.Message {
|
||||
m.Cmdy(target, s.Select, m.OptionSimple(model.STORY_UID), m.CommandKey()+"_uid", m.Option(model.UID))
|
||||
m.Option("_command", ice.GetTypeKey(target))
|
||||
m.Option("place_uid", m.Option(model.STORY_UID))
|
||||
s.SelectJoinUser(m)
|
||||
return m
|
||||
}
|
||||
func (s Table) changeStatus(m *ice.Message, from, to IssueStatus) {
|
||||
s.ChangeStatus(m, int(from), int(to), m.ActionKey()+"_time", m.Time())
|
||||
}
|
||||
func (s Table) ChangeStatus(m *ice.Message, from, to int, arg ...string) {
|
||||
s.Table.ChangeStatus(m, m.Option(model.STORY_UID), m.Option(model.UID), from, to, arg...)
|
||||
s.DashboardUpdate(m)
|
||||
}
|
||||
func (s Table) addCount(m *ice.Message, target ice.Any) Table {
|
||||
UID := s.Keys(target, model.UID)
|
||||
if m.IsErr() || m.Option(UID) == "" {
|
||||
return s
|
||||
}
|
||||
m.Cmd(target, s.AddCount, m.CommandKey()+"_count", kit.Select("-1", "1", m.ActionKey() == mdb.CREATE), m.Option(UID))
|
||||
return s
|
||||
}
|
||||
func (s Table) planCount(m *ice.Message) Table { return s.addCount(m, Plan{}) }
|
||||
func (s Table) issueCount(m *ice.Message) Table { return s.addCount(m, Issue{}) }
|
||||
func (s Table) taskCount(m *ice.Message) Table { return s.addCount(m, Task{}) }
|
||||
|
||||
type Tables struct{ Table }
|
||||
|
||||
|
21
src/production/deal.go
Normal file
21
src/production/deal.go
Normal file
@ -0,0 +1,21 @@
|
||||
package production
|
||||
|
||||
import (
|
||||
"shylinux.com/x/ice"
|
||||
"shylinux.com/x/operation/src/production/model"
|
||||
)
|
||||
|
||||
type deal struct {
|
||||
Table
|
||||
order string `data:"7"`
|
||||
fields string `data:"from_user_uid,to_user_uid,price,title,content"`
|
||||
create string `name:"create from_user_uid* to_user_uid* price* title* content" role:"leader"`
|
||||
}
|
||||
|
||||
func (s deal) List(m *ice.Message, arg ...string) {
|
||||
s.ValueList(m, arg).Display("")
|
||||
m.RenameAppend(model.TO_USER_UID, model.USER_UID)
|
||||
s.SelectJoinUser(m)
|
||||
}
|
||||
|
||||
func init() { ice.TeamCtxCmd(deal{}) }
|
9
src/production/deal.js
Normal file
9
src/production/deal.js
Normal file
@ -0,0 +1,9 @@
|
||||
Volcanos(chat.ONIMPORT, {
|
||||
_init: function(can, msg) {
|
||||
can.onimport.myView(can, msg, function(value) { return [
|
||||
{view: html.TITLE, list: [value.title||value.name||value.user_name, can.onimport.moneyView(can, value), can.onimport.titleAction(can, value)]},
|
||||
{view: html.STATUS, list: [value.uid.slice(0, 6), can.onimport.timeView(can, value), value.user_name]},
|
||||
{view: html.OUTPUT, list: [value.content||value.info]},
|
||||
] })
|
||||
},
|
||||
})
|
@ -10,72 +10,25 @@ import (
|
||||
type Design struct {
|
||||
Table
|
||||
order string `data:"3"`
|
||||
fields string `data:"title,content,design_status,begin_time,end_time,process_time,finish_time,issue_uid,plan_uid,user_uid"`
|
||||
create string `name:"create issue_uid* title* content* begin_time:select@date end_time:select@date" role:"worker"`
|
||||
modify string `name:"modify title* content* begin_time*:select@date end_time*:select@date" role:"worker"`
|
||||
fields string `data:"title,content,status,price,begin_time,end_time,process_time,finish_time,issue_uid,plan_uid,user_uid"`
|
||||
create string `name:"create issue_uid* title* content* price=1000 begin_time:select@date end_time:select@date" role:"worker"`
|
||||
modify string `name:"modify title* content* price* begin_time*:select@date end_time*:select@date" role:"worker"`
|
||||
}
|
||||
|
||||
func (s Design) Create(m *ice.Message, arg ...string) {
|
||||
s.ValueCreate(m, kit.ArgDef(arg, kit.Simple(model.BEGIN_TIME, m.Time(), model.END_TIME, m.Time("72h"))...)...)
|
||||
s.issueCount(m, "1")
|
||||
s.ValueCreate(m, kit.ArgDef(arg, kit.Simple(model.PRICE, "1000", model.BEGIN_TIME, m.Time(), model.END_TIME, m.Time("72h"))...)...)
|
||||
s.issueCount(m)
|
||||
s.SendMessage(s.GetCommandUID(m), "", "")
|
||||
}
|
||||
func (s Design) Remove(m *ice.Message, arg ...string) {
|
||||
s.ValueRemove(m, arg...)
|
||||
s.issueCount(m, "-1")
|
||||
s.issueCount(m)
|
||||
}
|
||||
func (s Design) List(m *ice.Message, arg ...string) {
|
||||
user_uid := m.Option(model.USER_UID)
|
||||
s.ValueList(m, arg).Table(func(value ice.Maps) {
|
||||
button := []ice.Any{}
|
||||
switch DesignStatus(kit.Int(value[model.DESIGN_STATUS])) {
|
||||
case DesignCreate:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Process)
|
||||
}
|
||||
case DesignProcess:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Finish)
|
||||
}
|
||||
case DesignFinish:
|
||||
kit.If(len(arg) == 2, func() { s.DoneMessage(m) })
|
||||
}
|
||||
m.PushButton(button...)
|
||||
}).Display("")
|
||||
s.Orders(m, model.STATUS, s.Desc(model.CREATED_AT))
|
||||
s.ValueList(m, arg).Table(func(value ice.Maps) { s.PushIssueButton(m, value, user_uid) }).Display("")
|
||||
s.SelectJoinPlan(m)
|
||||
s.StatusCount(m, arg...)
|
||||
}
|
||||
func (s Design) Process(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, DesignCreate, DesignProcess)
|
||||
}
|
||||
func (s Design) Finish(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, DesignProcess, DesignFinish)
|
||||
}
|
||||
|
||||
func init() { ice.TeamCtxCmd(Design{}) }
|
||||
|
||||
func (s Design) changeStatus(m *ice.Message, from, to DesignStatus) {
|
||||
s.ChangeStatus(m, int(from), int(to), m.ActionKey()+"_time", m.Time())
|
||||
}
|
||||
func (s Design) issueCount(m *ice.Message, value string) Design {
|
||||
if m.IsErr() || m.Option(model.ISSUE_UID) == "" {
|
||||
return s
|
||||
}
|
||||
m.Cmd(Issue{}, s.AddCount, model.DESIGN_COUNT, value, m.Option(model.ISSUE_UID))
|
||||
return s
|
||||
}
|
||||
|
||||
type DesignStatus int
|
||||
|
||||
const (
|
||||
DesignCreate DesignStatus = iota
|
||||
DesignProcess
|
||||
DesignFinish
|
||||
)
|
||||
|
||||
var DesignStatusList = map[DesignStatus]string{
|
||||
DesignCreate: "create",
|
||||
DesignProcess: "process",
|
||||
DesignFinish: "finish",
|
||||
}
|
||||
|
||||
func (s DesignStatus) String() string { return DesignStatusList[s] }
|
||||
|
@ -2,7 +2,8 @@ Volcanos(chat.ONIMPORT, {
|
||||
_init: function(can, msg) {
|
||||
can.onimport.myView(can, msg, function(value) { return [
|
||||
{view: html.TITLE, list: [value.title, can.onimport.textView(can, value)]},
|
||||
{view: html.STATUS, list: [can.onimport.beginTime(can, value), "计划:", value.plan_title]},
|
||||
{view: html.STATUS, list: [can.onimport.beginTime(can, value), can.onimport.unitView(can, value, "plan_title")]},
|
||||
value.price > 0 && {view: html.OUTPUT, list: [can.onimport.unitView(can, value, "price", "元")]},
|
||||
{view: html.OUTPUT, list: [value.content]}, can.onimport.titleAction(can, value),
|
||||
] })
|
||||
},
|
||||
|
@ -10,87 +10,45 @@ import (
|
||||
type Issue struct {
|
||||
Table
|
||||
order string `data:"2"`
|
||||
fields string `data:"title,content,level,issue_type,issue_status,price,link,design_count,task_count,begin_time,end_time,process_time,finish_time,plan_uid,user_uid"`
|
||||
create string `name:"create plan_uid* title* content* issue_type:select level:select price begin_time:select@date end_time:select@date" role:"worker"`
|
||||
modify string `name:"modify title* content* issue_type*:select level*:select price begin_time:select@date end_time:select@date" role:"worker"`
|
||||
reject string `name:"reject" role:"leader"`
|
||||
approve string `name:"approve" role:"leader"`
|
||||
submit string `name:"submit" role:"worker"`
|
||||
reback string `name:"reback" role:"leader"`
|
||||
payfor string `name:"payfor" role:"worker"`
|
||||
designCreate string `name:"designCreate title* content* begin_time:select@date end_time:select@date" role:"worker"`
|
||||
taskCreate string `name:"taskCreate title* content* begin_time:select@date end_time:select@date" role:"worker"`
|
||||
fields string `data:"title,content,level,issue_type,status,price,link,design_count,task_count,begin_time,end_time,process_time,finish_time,plan_uid,user_uid"`
|
||||
create string `name:"create plan_uid* title* content* issue_type:select level:select price=1000 begin_time:select@date end_time:select@date" role:"worker"`
|
||||
modify string `name:"modify title* content* issue_type*:select level*:select price* begin_time:select@date end_time:select@date" role:"worker"`
|
||||
designCreate string `name:"designCreate title* content* price=1000 begin_time:select@date end_time:select@date" role:"worker"`
|
||||
taskCreate string `name:"taskCreate title* content* price=1000 begin_time:select@date end_time:select@date" role:"worker"`
|
||||
designList string `name:"designList" role:"worker"`
|
||||
taskList string `name:"taskList" role:"worker"`
|
||||
meetList string `name:"meetList" role:"worker"`
|
||||
dealList string `name:"dealList" role:"worker"`
|
||||
applyCreate string `name:"applyCreate" role:"void"`
|
||||
}
|
||||
|
||||
func (s Issue) Create(m *ice.Message, arg ...string) {
|
||||
s.ValueCreate(m, kit.ArgDef(s.TransPrice(m, arg), kit.Simple(
|
||||
model.ISSUE_TYPE, IssueFeature, model.LEVEL, Level3, model.PRICE, "1000",
|
||||
model.BEGIN_TIME, m.Time(), model.END_TIME, m.Time("72h"),
|
||||
s.ValueCreate(m, kit.ArgDef(arg, kit.Simple(
|
||||
model.ISSUE_TYPE, IssueFeature, model.LEVEL, Level3,
|
||||
model.PRICE, "1000", model.BEGIN_TIME, m.Time(), model.END_TIME, m.Time("72h"),
|
||||
)...)...)
|
||||
s.planCount(m, "1").DashboardUpdate(m)
|
||||
s.planCount(m).DashboardUpdate(m)
|
||||
s.SendMessage(s.GetCommandUID(m), "", "")
|
||||
}
|
||||
func (s Issue) Remove(m *ice.Message, arg ...string) {
|
||||
s.ValueRemove(m, arg...)
|
||||
s.planCount(m, "-1").DashboardUpdate(m)
|
||||
s.planCount(m).DashboardUpdate(m)
|
||||
}
|
||||
func (s Issue) List(m *ice.Message, arg ...string) {
|
||||
isLeader, isWorker, user_uid := s.IsLeader(m), s.IsWorker(m), m.Option(model.USER_UID)
|
||||
if !s.IsWorker(m) {
|
||||
s.ApplyCheck(m, arg...)
|
||||
return
|
||||
}
|
||||
user_uid := m.Option(model.USER_UID)
|
||||
s.Orders(m, model.STATUS, model.DESIGN_COUNT, model.TASK_COUNT, s.Desc(model.CREATED_AT))
|
||||
s.ValueList(m, arg).Table(func(value ice.Maps) {
|
||||
button := []ice.Any{}
|
||||
switch IssueStatus(kit.Int(value[model.ISSUE_STATUS])) {
|
||||
case IssueCreate:
|
||||
if isLeader {
|
||||
button = append(button, s.Reject, s.Approve)
|
||||
}
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Modify, s.Remove)
|
||||
}
|
||||
case IssueApproved:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Process)
|
||||
}
|
||||
case IssueProcess:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Submit)
|
||||
}
|
||||
if isLeader && kit.Int(value[model.PRICE]) > 0 {
|
||||
// button = append(button, s.Payfor)
|
||||
}
|
||||
case IssueSubmit:
|
||||
if isLeader {
|
||||
button = append(button, s.Reback, s.Finish)
|
||||
}
|
||||
case IssueFinish:
|
||||
if isWorker {
|
||||
button = append(button, s.DesignCreate, s.TaskCreate)
|
||||
}
|
||||
if isLeader && kit.Int(value[model.PRICE]) > 0 {
|
||||
// button = append(button, s.Payfor)
|
||||
}
|
||||
kit.If(len(arg) == 2 && value[model.PRICE] == "0", func() { s.DoneMessage(m) })
|
||||
}
|
||||
m.PushButton(button...)
|
||||
s.PushIssueButton(m, value, user_uid, s.DesignCreate, s.TaskCreate)
|
||||
}).Display("")
|
||||
s.SelectJoinPlan(m)
|
||||
}
|
||||
func (s Issue) Reject(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, IssueCreate, IssueRejected)
|
||||
}
|
||||
func (s Issue) Approve(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, IssueCreate, IssueApproved)
|
||||
}
|
||||
func (s Issue) Process(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, IssueApproved, IssueProcess)
|
||||
}
|
||||
func (s Issue) Submit(m *ice.Message, arg ...string) {
|
||||
s.ChangeStatus(m, int(IssueProcess), int(IssueSubmit))
|
||||
}
|
||||
func (s Issue) Reback(m *ice.Message, arg ...string) {
|
||||
s.ChangeStatus(m, int(IssueSubmit), int(IssueProcess))
|
||||
s.StatusCount(m, arg...)
|
||||
}
|
||||
func (s Issue) Finish(m *ice.Message, arg ...string) {
|
||||
count := m.Cmd(Design{}, s.Select, "issue_uid = ? AND status != ?", m.Option(model.UID), DesignFinish).Length()
|
||||
count := m.Cmd(Design{}, s.Select, "issue_uid = ? AND status != ?", m.Option(model.UID), IssueFinish).Length()
|
||||
if m.WarnNotValid(count > 0, kit.Format("还有 %v 个未完成的设计", count)) {
|
||||
return
|
||||
}
|
||||
@ -100,26 +58,21 @@ func (s Issue) Finish(m *ice.Message, arg ...string) {
|
||||
}
|
||||
s.changeStatus(m, IssueSubmit, IssueFinish)
|
||||
}
|
||||
func (s Issue) DesignCreate(m *ice.Message, arg ...string) {
|
||||
s.OtherCreate(m, Design{}, model.ISSUE_UID, m.Option(model.UID), arg, m.OptionSimple(model.PLAN_UID))
|
||||
func (s Issue) DesignCreate(m *ice.Message, arg ...string) { s.OtherCreate(m, Design{}, arg...) }
|
||||
func (s Issue) DesignList(m *ice.Message, arg ...string) {
|
||||
s.OtherList(m, Design{}).Display("design.js")
|
||||
}
|
||||
func (s Issue) TaskCreate(m *ice.Message, arg ...string) {
|
||||
s.OtherCreate(m, Task{}, model.ISSUE_UID, m.Option(model.UID), arg, m.OptionSimple(model.PLAN_UID))
|
||||
func (s Issue) TaskCreate(m *ice.Message, arg ...string) { s.OtherCreate(m, Task{}, arg...) }
|
||||
func (s Issue) TaskList(m *ice.Message, arg ...string) { s.OtherList(m, Task{}).Display("task.js") }
|
||||
func (s Issue) MeetList(m *ice.Message, arg ...string) { s.OtherList(m, meet{}).Display("meet.js") }
|
||||
func (s Issue) DealList(m *ice.Message, arg ...string) {
|
||||
s.OtherList(m, deal{}).Display("deal.js")
|
||||
m.RenameAppend(model.TO_USER_UID, model.USER_UID)
|
||||
s.SelectJoinUser(m)
|
||||
}
|
||||
|
||||
func init() { ice.TeamCtxCmd(Issue{}) }
|
||||
|
||||
func (s Issue) changeStatus(m *ice.Message, from, to IssueStatus) {
|
||||
s.ChangeStatus(m, int(from), int(to), m.ActionKey()+"_time", m.Time())
|
||||
}
|
||||
func (s Issue) planCount(m *ice.Message, value string) Issue {
|
||||
if m.IsErr() || m.Option(model.PLAN_UID) == "" {
|
||||
return s
|
||||
}
|
||||
m.Cmd(Plan{}, s.AddCount, model.ISSUE_COUNT, value, m.Option(model.PLAN_UID))
|
||||
return s
|
||||
}
|
||||
|
||||
type IssueType int
|
||||
|
||||
const (
|
||||
|
@ -7,13 +7,14 @@ Volcanos(chat.ONIMPORT, {
|
||||
can.onimport.textView(can, value),
|
||||
]},
|
||||
{view: html.STATUS, list: [
|
||||
can.onimport.beginTime(can, value),
|
||||
"设计:", value.design_count+" 个",
|
||||
"任务:", value.task_count+" 个",
|
||||
"计划:", value.plan_title,
|
||||
(value.process_time||value.begin_time).split(" ")[0]+" ~ "+(value.finish_time||value.end_time).split(" ")[0],
|
||||
can.onimport.unitView(can, value, "design_count", "个"),
|
||||
can.onimport.unitView(can, value, "task_count", "个"),
|
||||
can.onimport.unitView(can, value, "plan_title"),
|
||||
]},
|
||||
value.price > 0 && {view: html.OUTPUT, list: ["报价: "+value.price+" 元"]},
|
||||
value.price > 0 && {view: html.OUTPUT, list: [can.onimport.unitView(can, value, "price", "元")]},
|
||||
{view: html.OUTPUT, list: [value.content]}, can.onimport.titleAction(can, value),
|
||||
] })
|
||||
can.onimport.otherList && can.onimport.otherList(can, msg, ["dealList", "meetList", "designList", "taskList"])
|
||||
},
|
||||
})
|
44
src/production/meet.go
Normal file
44
src/production/meet.go
Normal file
@ -0,0 +1,44 @@
|
||||
package production
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"shylinux.com/x/ice"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
type meet struct {
|
||||
Table
|
||||
order string `data:"6"`
|
||||
fields string `data:"title,content,link,meet_type,begin_time,end_time,issue_uid,plan_uid,company_uid,user_uid"`
|
||||
create string `name:"create issue_uid* meet_type* title* content* date time link*" role:"leader"`
|
||||
remove string `name:"remove" role:"leader"`
|
||||
}
|
||||
|
||||
func (s meet) Create(m *ice.Message, arg ...string) {
|
||||
t := kit.Time(m.Option("date") + " " + m.Option("time") + ":00")
|
||||
m.Option("begin_time", time.Unix(t, 0).Format(ice.MOD_TIME))
|
||||
m.Option("end_time", m.Option("date")+" "+m.Option("time")+":00")
|
||||
s.ValueCreate(m, m.OptionSimple("issue_uid,meet_type,title,content,link,begin_time,end_time")...)
|
||||
}
|
||||
func (s meet) List(m *ice.Message, arg ...string) {
|
||||
s.ValueList(m, arg).Display("")
|
||||
}
|
||||
|
||||
func init() { ice.TeamCtxCmd(meet{}) }
|
||||
|
||||
type MeetType int
|
||||
|
||||
const (
|
||||
MeetTalk MeetType = iota
|
||||
MeetValue
|
||||
MeetCheck
|
||||
)
|
||||
|
||||
var MeetTypeList = map[MeetType]string{
|
||||
MeetTalk: "需求沟通",
|
||||
MeetValue: "需求评审",
|
||||
MeetCheck: "项目验收",
|
||||
}
|
||||
|
||||
func (s MeetType) String() string { return MeetTypeList[s] }
|
9
src/production/meet.js
Normal file
9
src/production/meet.js
Normal file
@ -0,0 +1,9 @@
|
||||
Volcanos(chat.ONIMPORT, {
|
||||
_init: function(can, msg) {
|
||||
can.onimport.myView(can, msg, function(value) { return [
|
||||
{view: html.TITLE, list: [value.title||value.name||value.user_name, can.onimport.titleAction(can, value)]},
|
||||
{view: html.STATUS, list: [value.uid.slice(0, 6), can.onimport.timeView(can, value), value.user_name]},
|
||||
{view: html.OUTPUT, list: [value.content||value.info]},
|
||||
] })
|
||||
},
|
||||
})
|
@ -3,12 +3,14 @@ package model
|
||||
import "shylinux.com/x/mysql-story/src/db"
|
||||
|
||||
const (
|
||||
CREATED_AT = "created_at"
|
||||
UID = "uid"
|
||||
NAME = "name"
|
||||
INFO = "info"
|
||||
TYPE = "type"
|
||||
LEVEL = "level"
|
||||
STATUS = "status"
|
||||
COUNT = "count"
|
||||
PRICE = "price"
|
||||
LINK = "link"
|
||||
TITLE = "title"
|
||||
@ -16,6 +18,8 @@ const (
|
||||
VERSION = "version"
|
||||
USER_UID = "user_uid"
|
||||
USER_ROLE = "user_role"
|
||||
USER_NAME = "user_name"
|
||||
USER_AVATAR = "user_avatar"
|
||||
USER_STORY_ROLE = "user_story_role"
|
||||
STORY_UID = "story_uid"
|
||||
STORY_NAME = "story_name"
|
||||
@ -33,6 +37,9 @@ const (
|
||||
TASK_UID = "task_uid"
|
||||
TASK_STATUS = "task_status"
|
||||
CASE_STATUS = "case_status"
|
||||
MEET_TYPE = "meet_type"
|
||||
FROM_USER_UID = "from_user_uid"
|
||||
TO_USER_UID = "to_user_uid"
|
||||
MARKET_UID = "market_uid"
|
||||
BEGIN_TIME = "begin_time"
|
||||
END_TIME = "end_time"
|
||||
@ -66,7 +73,9 @@ type Issue struct {
|
||||
}
|
||||
type Design struct {
|
||||
Common
|
||||
IssueUID string `gorm:"type:char(32);index"`
|
||||
IssueUID string `gorm:"type:char(32);index"`
|
||||
RejectTime db.Time
|
||||
ApproveTime db.Time
|
||||
}
|
||||
type Task struct {
|
||||
Common
|
||||
@ -77,8 +86,31 @@ type Case struct {
|
||||
Common
|
||||
TaskUID string `gorm:"type:char(32);index"`
|
||||
}
|
||||
type Meet struct {
|
||||
db.ModelContent
|
||||
CompanyUID string `gorm:"type:char(32);index"`
|
||||
StoryUID string `gorm:"type:char(32);index"`
|
||||
PlanUID string `gorm:"type:char(32);index"`
|
||||
IssueUID string `gorm:"type:char(32);index"`
|
||||
Link string `gorm:"type:varchar(255)"`
|
||||
Type uint8 `gorm:"default:0"`
|
||||
BeginTime db.Time
|
||||
EndTime db.Time
|
||||
}
|
||||
type Deal struct {
|
||||
db.ModelContent
|
||||
CompanyUID string `gorm:"type:char(32);index"`
|
||||
StoryUID string `gorm:"type:char(32);index"`
|
||||
PlanUID string `gorm:"type:char(32);index"`
|
||||
IssueUID string `gorm:"type:char(32);index"`
|
||||
FromUserUID string `gorm:"type:char(32);index"`
|
||||
ToUserUID string `gorm:"type:char(32);index"`
|
||||
Price int `gorm:"default:0"`
|
||||
}
|
||||
|
||||
func init() { db.CmdModels("", &UserStory{}, &Story{}, &Plan{}, &Issue{}, &Design{}, &Task{}, &Case{}) }
|
||||
func init() {
|
||||
db.CmdModels("", &UserStory{}, &Story{}, &Plan{}, &Issue{}, &Design{}, &Task{}, &Case{}, &Meet{}, &Deal{})
|
||||
}
|
||||
|
||||
type Common struct {
|
||||
db.ModelContent
|
||||
|
@ -15,8 +15,8 @@ type Plan struct {
|
||||
modify string `name:"modify title* content version begin_time*:select@date end_time*:select@date" role:"leader"`
|
||||
remove string `name:"remove" role:"leader"`
|
||||
process string `name:"process" role:"leader"`
|
||||
finish string `name:"finish" role:"leader"`
|
||||
issueCreate string `name:"issueCreate title* content* issue_type:select level:select price begin_time:select@date end_time:select@date" role:"worker"`
|
||||
issueCreate string `name:"issueCreate title* content* issue_type:select level:select price=1000 begin_time:select@date end_time:select@date" role:"worker"`
|
||||
issueList string `name:"issueList" role:"worker"`
|
||||
}
|
||||
|
||||
func (s Plan) Create(m *ice.Message, arg ...string) {
|
||||
@ -25,7 +25,12 @@ func (s Plan) Create(m *ice.Message, arg ...string) {
|
||||
}
|
||||
func (s Plan) List(m *ice.Message, arg ...string) {
|
||||
isLeader, isWorker := s.IsLeader(m), s.IsWorker(m)
|
||||
defer kit.If(!isLeader, func() { m.SetResult().Action() })
|
||||
defer kit.If(!isLeader, func() {
|
||||
if m.Action(); m.Length() == 0 {
|
||||
m.SetResult("请等待管理员创建迭代计划")
|
||||
}
|
||||
})
|
||||
s.Orders(m, model.STATUS, model.ISSUE_COUNT, s.Desc(model.CREATED_AT))
|
||||
s.ValueList(m, arg).Table(func(value ice.Maps) {
|
||||
button := []ice.Any{}
|
||||
switch PlanStatus(kit.Int(value[model.PLAN_STATUS])) {
|
||||
@ -34,6 +39,9 @@ func (s Plan) List(m *ice.Message, arg ...string) {
|
||||
button = append(button, s.Process, s.Modify, s.Remove)
|
||||
}
|
||||
case PlanProcess:
|
||||
if isLeader && m.Option(model.MARKET_UID) == "" {
|
||||
// button = append(button, s.MarketInsert)
|
||||
}
|
||||
if isWorker {
|
||||
button = append(button, s.IssueCreate)
|
||||
}
|
||||
@ -47,24 +55,21 @@ func (s Plan) List(m *ice.Message, arg ...string) {
|
||||
kit.If(len(arg) == 2, func() { s.DoneMessage(m) })
|
||||
}
|
||||
m.PushButton(button...)
|
||||
}).Display("").DisplayCSS("").Sort("plan_status,issue_count,create_time")
|
||||
}).Display("").DisplayCSS("")
|
||||
s.StatusCount(m, arg...)
|
||||
}
|
||||
func (s Plan) Process(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, PlanCreate, PlanProcess)
|
||||
}
|
||||
func (s Plan) Finish(m *ice.Message, arg ...string) {
|
||||
count := m.Cmd(Issue{}, s.Select, "plan_uid = ? AND status != ?", m.Option(model.UID), IssueFinish).Length()
|
||||
if !m.WarnNotValid(count > 0, kit.Format("还有 %v 个未完成的需求", count)) {
|
||||
s.changeStatus(m, PlanProcess, PlanFinish)
|
||||
if m.WarnNotValid(count > 0, kit.Format("还有 %v 个未完成的需求", count)) {
|
||||
return
|
||||
}
|
||||
s.changeStatus(m, PlanProcess, PlanFinish)
|
||||
}
|
||||
func (s Plan) IssueCreate(m *ice.Message, arg ...string) {
|
||||
s.OtherCreate(m, Issue{}, model.PLAN_UID, m.Option(model.UID), arg)
|
||||
}
|
||||
func (s Table) OtherCreate(m *ice.Message, target ice.Any, arg ...ice.Any) {
|
||||
m.Cmdy(target, s.Create, kit.Simple(arg...))
|
||||
kit.If(!m.IsErr(), func() { m.ProcessField(target, []string{m.Option(model.STORY_UID), m.Result()}) })
|
||||
}
|
||||
func (s Plan) IssueCreate(m *ice.Message, arg ...string) { s.OtherCreate(m, Issue{}, arg...) }
|
||||
func (s Plan) IssueList(m *ice.Message, arg ...string) { s.OtherList(m, Issue{}).Display("issue.js") }
|
||||
|
||||
func init() { ice.TeamCtxCmd(Plan{}) }
|
||||
|
||||
|
@ -2,8 +2,9 @@ Volcanos(chat.ONIMPORT, {
|
||||
_init: function(can, msg) {
|
||||
can.onimport.myView(can, msg, function(value) { return [
|
||||
{view: html.TITLE, list: [value.title, value.version, can.onimport.textView(can, value)]},
|
||||
{view: html.STATUS, list: [can.onimport.beginTime(can, value), "需求量:", value.issue_count+" 个"]},
|
||||
{view: html.STATUS, list: [can.onimport.beginTime(can, value), can.onimport.unitView(can, value, "issue_count", "个")]},
|
||||
{view: html.OUTPUT, list: [value.content]}, can.onimport.titleAction(can, value),
|
||||
] })
|
||||
can.onimport.otherList && can.onimport.otherList(can, msg, "issueList")
|
||||
},
|
||||
})
|
||||
})
|
||||
|
@ -17,8 +17,8 @@ func (s Portal) AfterPlaceAuth(m *ice.Message, arg ...string) {
|
||||
defer s.DashboardCreate(m, "")()
|
||||
s.DashboardInsert(m, 1, "需求总量", "个", Issue{}, "")
|
||||
s.DashboardInsert(m, 2, "需求待办", "个", Issue{}, "", "story_uid = ? AND status != ? AND status != ?", m.Option(model.STORY_UID), IssueRejected, IssueFinish)
|
||||
s.DashboardInsert(m, 4, "任务待办", "个", Task{}, "", "story_uid = ? AND status != ?", m.Option(model.STORY_UID), TaskFinish)
|
||||
s.DashboardInsert(m, 3, "任务总量", "个", Task{}, "")
|
||||
s.DashboardInsert(m, 3, "任务待办", "个", Task{}, "", "story_uid = ? AND status != ?", m.Option(model.STORY_UID), TaskFinish)
|
||||
s.DashboardInsert(m, 4, "任务总量", "个", Task{}, "")
|
||||
}
|
||||
|
||||
func init() { gonganxitong.PortalCmd(Portal{Portal: guanlixitong.NewPortal(userStory{}, story{})}) }
|
||||
|
@ -1,20 +1,27 @@
|
||||
{
|
||||
"portal": "产品迭代", "member": "项目成员",
|
||||
"plan": "迭代计划", "issue": "产品需求", "design": "界面设计", "task": "开发任务", "case": "测试用例",
|
||||
"process": "开始", "submit": "提交", "reback": "返工", "finish": "完成", "payfor": "支付",
|
||||
"issueCreate": "创建需求", "designCreate": "创建设计", "taskCreate": "创建任务", "caseCreate": "创建用例",
|
||||
"meet": "会议记录", "deal": "支付记录",
|
||||
"process": "开始", "submit": "提交", "reback": "返工", "finish": "完成", "discuss": "约会", "payfor": "支付",
|
||||
"issueCreate": "设计原型", "designCreate": "美化界面", "taskCreate": "开发任务", "caseCreate": "测试用例",
|
||||
"issueList": "设计原型", "designList": "美化界面", "taskList": "开发任务", "caseList": "测试用例",
|
||||
"dealList": "支付记录",
|
||||
"meetList": "会议记录",
|
||||
"style": {
|
||||
"process": "notice",
|
||||
"submit": "notice",
|
||||
"reback": "notice",
|
||||
"finish": "notice",
|
||||
"payfor": "notice",
|
||||
"discuss": "notice",
|
||||
"issueCreate": "notice",
|
||||
"designCreate": "notice",
|
||||
"taskCreate": "notice",
|
||||
"caseCreate": "notice"
|
||||
},
|
||||
"icons": {
|
||||
"meet": "issue.png",
|
||||
"deal": "issue.png",
|
||||
"plan": "plan.png",
|
||||
"issue": "issue.png",
|
||||
"design": "design.png",
|
||||
@ -22,6 +29,7 @@
|
||||
"case": "case.png"
|
||||
},
|
||||
"input": {
|
||||
"date": "日期",
|
||||
"My Story": "我的产品",
|
||||
"user_story_role": "用户角色",
|
||||
"story_name": "产品名称",
|
||||
@ -36,12 +44,15 @@
|
||||
"design_status": "设计状态",
|
||||
"design_count": "设计数量",
|
||||
"task_uid": "开发任务",
|
||||
"from_user_uid": "付款人",
|
||||
"to_user_uid": "收款人",
|
||||
"task_status": "任务状态",
|
||||
"task_count": "任务数量",
|
||||
"case_status": "用例状态",
|
||||
"case_count": "用例数量",
|
||||
"process_time": "开始时间",
|
||||
"finish_time": "完成时间",
|
||||
"comment": "备注",
|
||||
"level": "优先级"
|
||||
},
|
||||
"value": {
|
||||
@ -63,11 +74,6 @@
|
||||
"military": "军用软件",
|
||||
"system": "系统软件"
|
||||
},
|
||||
"plan_status": {
|
||||
"create": "待开始",
|
||||
"process": "进行中",
|
||||
"finish": "已完成"
|
||||
},
|
||||
"issue_type": {
|
||||
"feature": "功能",
|
||||
"bugfix": "问题",
|
||||
@ -75,11 +81,16 @@
|
||||
"bugfix": "danger"
|
||||
}
|
||||
},
|
||||
"issue_status": {
|
||||
"plan_status": {
|
||||
"create": "待开始",
|
||||
"process": "进行中",
|
||||
"finish": "已完成"
|
||||
},
|
||||
"status": {
|
||||
"create": "待评审",
|
||||
"rejected": "已驳回",
|
||||
"approved": "待调研",
|
||||
"process": "调研中",
|
||||
"approved": "待设计",
|
||||
"process": "设计中",
|
||||
"submit": "已提交",
|
||||
"finish": "已完成",
|
||||
"style": {
|
||||
@ -89,14 +100,6 @@
|
||||
"submit": "danger"
|
||||
}
|
||||
},
|
||||
"design_status": {
|
||||
"create": "待设计",
|
||||
"process": "设计中",
|
||||
"finish": "已完成",
|
||||
"style": {
|
||||
"create": "danger"
|
||||
}
|
||||
},
|
||||
"task_status": {
|
||||
"create": "待开发",
|
||||
"process": "开发中",
|
||||
|
6
src/production/portal.shy
Normal file
6
src/production/portal.shy
Normal file
@ -0,0 +1,6 @@
|
||||
chapter "产品迭代"
|
||||
section "迭代计划"
|
||||
section "产品需求"
|
||||
section "界面设计"
|
||||
section "开发任务"
|
||||
section "测试用例"
|
@ -10,70 +10,45 @@ import (
|
||||
type Task struct {
|
||||
Table
|
||||
order string `data:"4"`
|
||||
fields string `data:"title,content,task_status,case_count,begin_time,end_time,process_time,finish_time,issue_uid,plan_uid,user_uid"`
|
||||
fields string `data:"title,content,status,case_count,begin_time,end_time,process_time,finish_time,issue_uid,plan_uid,user_uid"`
|
||||
create string `name:"create issue_uid* title* content* begin_time:select@date end_time:select@date" role:"worker"`
|
||||
modify string `name:"modify title* content* begin_time*:select@date end_time*:select@date" role:"worker"`
|
||||
caseCreate string `name:"caseCreate title* content* begin_time:select@date end_time:select@date" role:"worker"`
|
||||
caseCreate string `name:"caseCreate title* content*" role:"worker"`
|
||||
}
|
||||
|
||||
func (s Task) Create(m *ice.Message, arg ...string) {
|
||||
s.ValueCreate(m, kit.ArgDef(arg, kit.Simple(model.BEGIN_TIME, m.Time(), model.END_TIME, m.Time("72h"))...)...)
|
||||
s.issueCount(m, "1").DashboardUpdate(m)
|
||||
s.issueCount(m).DashboardUpdate(m)
|
||||
s.SendMessage(s.GetCommandUID(m), "", "")
|
||||
}
|
||||
func (s Task) Remove(m *ice.Message, arg ...string) {
|
||||
s.ValueRemove(m, arg...)
|
||||
s.issueCount(m, "-1").DashboardUpdate(m)
|
||||
s.issueCount(m).DashboardUpdate(m)
|
||||
}
|
||||
func (s Task) List(m *ice.Message, arg ...string) {
|
||||
isWorker, user_uid := s.IsWorker(m), m.Option(model.USER_UID)
|
||||
s.ValueList(m, arg).Table(func(value ice.Maps) {
|
||||
button := []ice.Any{}
|
||||
switch TaskStatus(kit.Int(value[model.TASK_STATUS])) {
|
||||
case TaskCreate:
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Process)
|
||||
}
|
||||
case TaskProcess:
|
||||
if isWorker {
|
||||
button = append(button, s.CaseCreate)
|
||||
}
|
||||
if user_uid == value[model.USER_UID] {
|
||||
button = append(button, s.Finish)
|
||||
}
|
||||
case TaskFinish:
|
||||
kit.If(len(arg) == 2, func() { s.DoneMessage(m) })
|
||||
}
|
||||
m.PushButton(button...)
|
||||
}).Display("")
|
||||
user_uid := m.Option(model.USER_UID)
|
||||
s.Orders(m, model.STATUS, model.CASE_COUNT, s.Desc(model.CREATED_AT))
|
||||
s.ValueList(m, arg).Table(func(value ice.Maps) { s.PushTaskButton(m, value, user_uid, s.CaseCreate) }).Display("")
|
||||
m.RenameAppend(model.STATUS, model.TASK_STATUS)
|
||||
s.SelectJoinPlan(m)
|
||||
s.StatusCount(m, arg...)
|
||||
}
|
||||
func (s Task) Process(m *ice.Message, arg ...string) {
|
||||
s.changeStatus(m, TaskCreate, TaskProcess)
|
||||
}
|
||||
func (s Task) Finish(m *ice.Message, arg ...string) {
|
||||
count := m.Cmd(Case{}, s.Select, "task_uid = ? AND status != ?", m.Option(model.UID), CaseFinish).Length()
|
||||
count := m.Cmd(Case{}, s.Select, "task_uid = ? AND status != ?", m.Option(model.UID), TaskFinish).Length()
|
||||
if m.WarnNotValid(count > 0, kit.Format("还有 %v 个未完成的用例", count)) {
|
||||
return
|
||||
}
|
||||
s.changeStatus(m, TaskProcess, TaskFinish)
|
||||
}
|
||||
func (s Task) CaseCreate(m *ice.Message, arg ...string) {
|
||||
s.OtherCreate(m, Case{}, model.TASK_UID, m.Option(model.UID), arg, m.OptionSimple(model.PLAN_UID))
|
||||
}
|
||||
func (s Task) CaseCreate(m *ice.Message, arg ...string) { s.OtherCreate(m, Case{}, arg...) }
|
||||
|
||||
func init() { ice.TeamCtxCmd(Task{}) }
|
||||
|
||||
func (s Task) changeStatus(m *ice.Message, from, to TaskStatus) {
|
||||
s.ChangeStatus(m, int(from), int(to), m.ActionKey()+"_time", m.Time())
|
||||
s.DashboardUpdate(m)
|
||||
}
|
||||
func (s Task) issueCount(m *ice.Message, value string) Task {
|
||||
if m.IsErr() || m.Option(model.ISSUE_UID) == "" {
|
||||
return s
|
||||
}
|
||||
m.Cmd(Issue{}, s.AddCount, model.TASK_COUNT, value, m.Option(model.ISSUE_UID))
|
||||
return s
|
||||
}
|
||||
|
||||
type TaskStatus int
|
||||
|
@ -2,7 +2,10 @@ Volcanos(chat.ONIMPORT, {
|
||||
_init: function(can, msg) {
|
||||
can.onimport.myView(can, msg, function(value) { return [
|
||||
{view: html.TITLE, list: [value.title, can.onimport.textView(can, value)]},
|
||||
{view: html.STATUS, list: [can.onimport.beginTime(can, value), "用例:", value.case_count+" 个", "计划:", value.plan_title]},
|
||||
{view: html.STATUS, list: [can.onimport.beginTime(can, value),
|
||||
can.onimport.unitView(can, value, "case_count", "个"),
|
||||
can.onimport.unitView(can, value, "plan_title"),
|
||||
]},
|
||||
{view: html.OUTPUT, list: [value.content]}, can.onimport.titleAction(can, value),
|
||||
] })
|
||||
},
|
||||
|
@ -8,6 +8,15 @@
|
||||
"time": "2024-09-12 20:43:01.619"
|
||||
}
|
||||
},
|
||||
"23769af348b5bf39fce16d2257889544": {
|
||||
"meta": {
|
||||
"icons": "src/production/issue.png",
|
||||
"index": "web.team.production.deal",
|
||||
"name": "支付记录",
|
||||
"order": "7",
|
||||
"time": "2025-04-28 09:30:23.328"
|
||||
}
|
||||
},
|
||||
"247b484fb13394452bc978e5ecad33ff": {
|
||||
"meta": {
|
||||
"icons": "/p/src/gonganxitong/apply.png?pod=20240724-community",
|
||||
@ -21,6 +30,7 @@
|
||||
"2cc2b9d11344506a6b0bbb0dbdde2d43": {
|
||||
"meta": {
|
||||
"auth": "issued",
|
||||
"enable": "false",
|
||||
"icons": "https://img.icons8.com/officel/80/online-store.png",
|
||||
"index": "web.team.production.goodslist",
|
||||
"name": "在线商城",
|
||||
@ -42,6 +52,7 @@
|
||||
"2f55a878524db4227e7476307269db05": {
|
||||
"meta": {
|
||||
"auth": "issued",
|
||||
"enable": "false",
|
||||
"icons": "https://img.icons8.com/officel/80/online-payment-with-a-credit-card.png",
|
||||
"index": "web.team.production.paymentlist",
|
||||
"name": "在线支付",
|
||||
@ -50,6 +61,15 @@
|
||||
"time": "2024-11-23 17:07:01.083"
|
||||
}
|
||||
},
|
||||
"3be1265611cf96a9d61bd4c2c879db70": {
|
||||
"meta": {
|
||||
"icons": "src/production/issue.png",
|
||||
"index": "web.team.production.meet",
|
||||
"name": "会议记录",
|
||||
"order": "6",
|
||||
"time": "2025-04-28 09:30:23.334"
|
||||
}
|
||||
},
|
||||
"50dd2633fafc2efb90760b602f1500ea": {
|
||||
"meta": {
|
||||
"icons": "/p/src/gonganxitong/notice.png?pod=20240724-community",
|
||||
@ -118,6 +138,7 @@
|
||||
"7cf76afacb83fabb3d6a6ffaf48b6066": {
|
||||
"meta": {
|
||||
"auth": "issued",
|
||||
"enable": "false",
|
||||
"icons": "https://img.icons8.com/officel/80/documents.png",
|
||||
"index": "web.team.production.document",
|
||||
"name": "在线文档",
|
||||
@ -165,6 +186,7 @@
|
||||
"a9b5b213c868653f1a060c3231d57e8f": {
|
||||
"meta": {
|
||||
"auth": "issued",
|
||||
"enable": "false",
|
||||
"icons": "https://img.icons8.com/officel/80/agreement.png",
|
||||
"index": "web.team.production.contract",
|
||||
"name": "在线合同",
|
||||
@ -204,6 +226,7 @@
|
||||
"c9559beab992f8b46b9cfa4a196e61e8": {
|
||||
"meta": {
|
||||
"auth": "issued",
|
||||
"enable": "false",
|
||||
"icons": "https://img.icons8.com/officel/80/ios-photos.png",
|
||||
"index": "web.team.production.photo",
|
||||
"name": "在线相册",
|
||||
@ -226,6 +249,7 @@
|
||||
"cea1324e3dca123f6560dee5c559a587": {
|
||||
"meta": {
|
||||
"auth": "issued",
|
||||
"enable": "false",
|
||||
"icons": "https://img.icons8.com/officel/80/video-conference.png",
|
||||
"index": "web.team.production.meeting",
|
||||
"name": "在线会议",
|
||||
|
Loading…
x
Reference in New Issue
Block a user