2025-06-10 12:54:50 +08:00

477 lines
17 KiB
Go

package production
import (
"path"
"strings"
"shylinux.com/x/ice"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/gonganxitong"
"shylinux.com/x/enterprise/src/guanlixitong"
"shylinux.com/x/operation/src/production/model"
)
type Table struct {
guanlixitong.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"`
submit string `name:"submit link*" role:"worker"`
finish string `name:"finish" role:"leader"`
reback string `name:"reback" role:"leader"`
cancel string `name:"cancel" role:"leader"`
trash string `name:"trash" role:"leader"`
list string `name:"list story_uid uid auto" role:"void"`
preview string `name:"preview" role:"worker"`
program string `name:"program" role:"worker"`
discuss string `name:"discuss meet_type* title* content meet_link* date* time*" role:"leader"`
addNote string `name:"addNote title content to_user_uid:select" help:"备注" role:"worker"`
setScore string `name:"setScore score" help:"评分" role:"leader"`
payfor string `name:"payfor price* title* content" role:"leader"`
upload string `name:"upload" role:"worker"`
download string `name:"download" style:"notice" role:"worker"`
fileCreate string `name:"fileCreate title* content file_type*:select file_link*@upload" help:"上传附件" role:"worker"`
dateInsert string `name:"dateInsert" help:"约会" role:"leader"`
planList string `name:"planList" role:"worker"`
issueList string `name:"issueList" role:"worker"`
designList string `name:"designList" role:"worker"`
taskList string `name:"taskList" role:"worker"`
caseList string `name:"caseList" role:"worker"`
noteList string `name:"noteList" role:"worker"`
fileList string `name:"fileList" role:"worker"`
meetList string `name:"meetList" role:"worker"`
dealList string `name:"dealList" role:"worker"`
}
func (s Table) Inputs(m *ice.Message, arg ...string) {
switch arg[0] {
case model.USER_STORY_ROLE:
s.InputsListRole(m, UserStoryRoleList, arg...)
case model.STORY_TYPE:
s.InputsList(m, StoryTypeList, arg...)
case model.PLAN_UID:
s.InputsUID(m, arg, Plan{}, m.OptionSimple(model.STORY_UID)...)
case model.PLAN_TYPE:
s.InputsList(m, PlanTypeList, arg...)
case model.ISSUE_UID:
s.InputsUID(m, arg, Issue{}, m.OptionSimple(model.STORY_UID)...)
case model.ISSUE_TYPE:
s.InputsList(m, IssueTypeList, arg...)
case model.TASK_UID:
s.InputsUID(m, arg, Task{}, m.OptionSimple(model.STORY_UID)...)
case model.MEET_TYPE:
s.InputsList(m, MeetTypeList, arg...)
case model.FILE_TYPE:
s.InputsList(m, FileTypeList, arg...)
case model.LEVEL:
s.InputsList(m, LevelList, arg...)
case model.VERSION:
m.Push(arg[0], "v1", "v2", "v3", "v4", "v5")
case nfs.PATH:
m.Option(ice.MSG_USERROLE, aaa.TECH)
m.Cmdy(web.SPACE, m.Option(web.SPACE), nfs.DIR, nfs.SRC, nfs.PATH)
case ctx.INDEX:
msg := m.Spawn()
s.Table.Inputs(msg, arg...)
msg.Table(func(value ice.Maps) {
if strings.HasSuffix(value[arg[0]], ".portal") {
m.Push(arg[0], value[arg[0]])
}
})
default:
switch m.Option(ctx.ACTION) {
case "discuss":
switch arg[0] {
case "date":
for i := 0; i < 5; i++ {
m.Push(arg[0], strings.Split(m.Time(kit.Format("%dh", i*24)), " ")[0])
}
case "time":
for i := 38; 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 {
m.RewriteAppend(func(value, key string, index int) string {
switch key {
case model.USER_STORY_ROLE:
value = UserStoryRole(kit.Int(value)).String()
case model.STORY_TYPE:
value = StoryType(kit.Int(value)).String()
case model.PLAN_TYPE:
value = PlanType(kit.Int(value)).String()
case model.PLAN_STATUS:
value = PlanStatus(kit.Int(value)).String()
case model.ISSUE_TYPE:
value = IssueType(kit.Int(value)).String()
case model.ISSUE_STATUS, model.DESIGN_STATUS, model.TASK_STATUS, model.CASE_STATUS, model.STATUS:
value = IssueStatus(kit.Int(value)).String()
case model.MEET_TYPE:
value = MeetType(kit.Int(value)).String()
case model.FILE_TYPE:
value = FileType(kit.Int(value)).String()
case model.FILE_SIZE:
value = kit.FmtSize(kit.Int(value))
case model.LEVEL:
value = Level(kit.Int(value)).String()
}
return value
})
return s.Table.RewriteAppend(m)
}
func (s Table) CheckRole(m *ice.Message, arg ...string) {
role := UserStoryRole(s.UserPlaceRole(m))
m.WarnNotRight(!kit.IsIn(role.String(), append(arg, UserStoryCreator.String())...), role.String())
}
func (s Table) DateInsert(m *ice.Message, arg ...string) {
m.ProcessField(Date{}, []string{m.Option(model.STORY_UID)}, m.OptionSimple(model.ISSUE_UID)...)
}
func (s Table) PushIssueButton(m *ice.Message, value ice.Maps, arg ...ice.Any) {
user_uid := m.Option(ice.MSG_USERUID)
button := []ice.Any{}
defer func() { m.PushButton(button...) }()
isCreator, isLeader, isWorker := s.IsCreator(m), s.IsLeader(m), s.IsWorker(m)
isLeaderApproved := isCreator || (isLeader && s.SettingIsOn(m, LEADER_APPROVED))
isLeaderFinish := isCreator || (isLeader && s.SettingIsOn(m, LEADER_FINISH))
isLeaderPayfor := isCreator || (isLeader && s.SettingIsOn(m, LEADER_PAYFOR))
kit.If(value[model.PLAN_TITLE] == "", func() { button = append(button, s.BindPlan) })
switch IssueStatus(kit.Int(value[model.STATUS])) {
case IssueCreate:
if isLeader {
button = append(button, s.DateInsert)
}
if isWorker {
button = append(button, s.AddNote)
}
if isLeaderApproved {
button = append(button, s.Approve)
}
if isLeader {
button = append(button, s.Reject)
}
if user_uid == value[model.USER_UID] {
button = append(button, s.Modify, s.Remove)
}
case IssueRejected:
if isLeaderApproved {
button = append(button, s.Trash)
}
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 isWorker {
button = append(button, arg...)
}
if isLeaderFinish {
button = append(button, s.Cancel)
}
case IssueSubmit:
if isWorker && value[model.LINK] != "" {
button = append(button, s.Preview)
}
if isWorker {
button = append(button, s.AddNote)
}
if isWorker {
button = append(button, s.FileCreate)
}
if isWorker {
button = append(button, arg...)
}
if isLeaderFinish {
button = append(button, s.Finish)
}
if isLeader {
button = append(button, s.Reback)
}
case IssueFinish:
if isWorker && value[model.LINK] != "" {
button = append(button, s.Preview)
}
if value[model.USER_UID] == m.Option(ice.MSG_USERUID) && PlanStatus(kit.Int(value[model.PLAN_STATUS])) != PlanFinish {
button = append(button, s.FileCreate)
} else if isLeader {
button = append(button, s.FileCreate)
}
if isWorker {
button = append(button, arg...)
}
if isLeaderPayfor && value[model.SCORE] == "0" {
button = append(button, s.SetScore)
}
if isLeaderPayfor && PlanStatus(kit.Int(value[model.PLAN_STATUS])) != PlanFinish {
button = append(button, s.Payfor)
}
kit.If(m.FieldsIsDetail(), func() { s.DoneMessage(m) })
case IssueCancel:
if isLeaderApproved {
button = append(button, s.Trash)
}
}
}
func (s Table) PushTaskButton(m *ice.Message, value ice.Maps, arg ...ice.Any) {
user_uid := m.Option(ice.MSG_USERUID)
button := []ice.Any{}
defer func() { m.PushButton(button...) }()
isCreator, isLeader, isWorker := s.IsCreator(m), s.IsLeader(m), s.IsWorker(m)
isLeaderFinish := isCreator || (isLeader && s.SettingIsOn(m, LEADER_FINISH))
switch IssueStatus(kit.Int(value[model.STATUS])) {
case IssueCreate:
if user_uid == value[model.USER_UID] {
button = append(button, s.Process, s.Modify, s.Remove)
}
case IssueProcess:
if isWorker {
button = append(button, arg...)
}
if user_uid == value[model.USER_UID] {
button = append(button, s.Finish)
}
if isLeaderFinish {
button = append(button, s.Cancel)
}
case IssueFinish:
if isWorker {
button = append(button, arg...)
}
kit.If(m.FieldsIsDetail(), func() { s.DoneMessage(m) })
}
}
func (s Table) SelectJoinPlan(m *ice.Message, arg ...string) {
s.SelectJoin(m, Plan{}, model.TITLE, model.STATUS)
}
func (s Table) StatusPrice(m *ice.Message, arg ...string) {
if m.Length() > 0 && len(arg) < 2 {
msg := m.Spawn()
s.Fields(msg, "sum(price) AS price")
s.Select(msg, model.STORY_UID, arg[0]).Table(func(value ice.Maps) {
m.Echo(model.PRICE).Echo(": ").Echo(kit.Format(kit.Int(value[model.PRICE]) / 100)).Echo(" 元")
})
}
}
func (s Table) UserInfo(m *ice.Message, arg ...string) {
m.ProcessField(care{}, []string{m.Option(model.STORY_UID), m.Option(model.UID)}, arg...)
}
func (s care) UserInfo(m *ice.Message, arg ...string) {
m.Cmdy(s.PrefixPortal(m), s.UserInfo, arg)
}
func (s Table) Reject(m *ice.Message, arg ...string) {
s.changeStatus(m, IssueCreate, IssueRejected)
s.sendTemplate(m, "", "", "")
}
func (s Table) Approve(m *ice.Message, arg ...string) {
s.changeStatus(m, IssueCreate, IssueApproved)
s.sendTemplate(m, "", "", "", arg...)
}
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) Finish(m *ice.Message, arg ...string) {
s.changeStatus(m, IssueSubmit, IssueFinish)
s.sendTemplate(m, "", "", "")
}
func (s Table) Reback(m *ice.Message, arg ...string) {
s.ChangeStatus(m, int(IssueSubmit), int(IssueProcess))
s.sendTemplate(m, "", "", "")
}
func (s Table) Cancel(m *ice.Message, arg ...string) {
s.ChangeStatus(m, int(IssueProcess), int(IssueCancel))
s.sendTemplate(m, "", "", "")
}
func (s Table) Trash(m *ice.Message, arg ...string) {
s.Delete(m, m.OptionSimple(model.UID, model.STORY_UID)...)
}
func (s Table) Preview(m *ice.Message, arg ...string) {
m.OptionDefault(model.LINK, m.Option(model.MEET_LINK))
m.ProcessOpen(m.OptionDefault(model.LINK, web.S(m.Option(web.SPACE))+web.C(m.Option(ctx.INDEX))))
}
func (s Table) sendTemplate(m *ice.Message, from, to, title string, arg ...string) {
msg := s.Select(m.Spawn(), m.OptionSimple(model.UID)...)
s.SendTemplate(m, from, msg.Append(model.USER_UID), title, arg...)
}
func (s Table) coderLink(m *ice.Message, arg ...string) string {
p := path.Base(m.Option(nfs.PATH))
return kit.MergeURL(web.S(m.Option(web.SPACE))+web.C("web.team.production.coder"),
nfs.PATH, nfs.SRC, nfs.FILE, path.Join(p, "portal.go"),
m.OptionSimple(model.STORY_UID, model.ISSUE_UID),
)
}
func (s Table) Program(m *ice.Message, arg ...string) {
m.ProcessOpen(s.coderLink(m))
}
func (s Table) Discuss(m *ice.Message, arg ...string) {
s.issueOtherCreate(m, Meet{}, arg...)
}
func (s Issue) Discuss(m *ice.Message, arg ...string) {
s.commonOtherCreate(m, Meet{}, arg...)
}
func (s Table) AddNote(m *ice.Message, arg ...string) {
m.Cmd(Note{}, s.Create, arg)
}
func (s Issue) AddNote(m *ice.Message, arg ...string) {
m.Cmd(Note{}, s.Create, arg, model.ISSUE_UID, m.Option(model.UID), m.OptionSimple(model.PLAN_UID))
}
func (s Design) AddNote(m *ice.Message, arg ...string) {
m.Cmd(Note{}, s.Create, arg, m.OptionSimple(model.ISSUE_UID), m.OptionSimple(model.PLAN_UID))
}
func (s Table) SetScore(m *ice.Message, arg ...string) {
s.Update(m, arg, m.OptionSimple(model.UID, model.STORY_UID)...)
}
func (s Table) Payfor(m *ice.Message, arg ...string) {
s.issueOtherCreate(m, Deal{}, arg...)
}
func (s Issue) Payfor(m *ice.Message, arg ...string) {
s.commonOtherCreate(m, Deal{}, arg...)
}
func (s Table) Upload(m *ice.Message, arg ...string) {
up := kit.Simple(m.Optionv(ice.MSG_UPLOAD))
m.Echo(m.UploadSave("usr/local/storage/" + up[0]))
}
func (s Table) FileCreate(m *ice.Message, arg ...string) {
s.issueOtherCreate(m, File{}, arg...)
msg := m.Cmd(Plan{}, s.Select, model.UID, m.Option(model.PLAN_UID))
s.sendTemplate(m, "", msg.Append(model.USER_UID), "")
}
func (s Issue) FileCreate(m *ice.Message, arg ...string) {
s.commonOtherCreate(m, File{}, arg...)
}
func (s Table) issueOtherCreate(m *ice.Message, target ice.Any, arg ...string) {
s.OtherCreate(m, target, kit.Simple(m.OptionSimple(model.ISSUE_UID), arg)...)
}
func (s Table) commonOtherCreate(m *ice.Message, target ice.Any, arg ...string) {
s.OtherCreate(m, target, kit.Simple(m.CommandKey()+"_uid", m.Option(model.UID), arg)...)
}
func (s Table) OtherCreate(m *ice.Message, target ice.Any, arg ...string) {
if m.ActionKeyIsIn(s.Discuss, s.Payfor) {
msg := s.Select(m, model.UID, m.Option(model.UID))
arg = append(arg, model.FROM_USER_UID, m.Option(model.USER_UID), model.TO_USER_UID, msg.Append(model.USER_UID))
}
kit.If(m.CommandKey() != "plan", func() { arg = append(arg, m.OptionSimple(model.PLAN_UID)...) })
m.Cmdy(target, s.Create, 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) {
m.Cmdy(target, s.Select, arg).Display(kit.Select("", strings.Split(ice.GetTypeKey(target), "."), -1) + ".js")
m.Option("_other_cmd", ice.GetTypeKey(target))
}
func (s Table) commonOtherList(m *ice.Message, target ice.Any, arg ...string) *ice.Message {
if m.Option(model.ISSUE_UID) == "" {
s.OtherList(m, target, kit.Simple(m.CommandKey()+"_uid", m.Option(model.UID))...)
} else if ice.GetTypeKey(target) == ice.GetTypeKey(Issue{}) {
s.OtherList(m, target, model.UID, m.Option(model.ISSUE_UID))
} else {
s.OtherList(m, target, model.ISSUE_UID, m.Option(model.ISSUE_UID))
}
m.RenameAppend(model.TO_USER_UID, model.USER_UID)
return m
}
func (s Table) otherListButton(m *ice.Message, arg ...string) {
m.Table(func(value ice.Maps) {
switch IssueStatus(kit.Int(value[model.STATUS])) {
case IssueSubmit, IssueFinish:
if value[web.LINK] != "" {
m.PushButton(s.Preview)
break
}
fallthrough
default:
m.PushButton()
}
})
}
func (s Table) PlanList(m *ice.Message, arg ...string) {
s.OtherList(m, Plan{}, model.UID, m.Option(model.PLAN_UID))
}
func (s Table) IssueList(m *ice.Message, arg ...string) {
s.commonOtherList(m, Issue{})
s.otherListButton(m)
}
func (s Table) DesignList(m *ice.Message, arg ...string) {
s.commonOtherList(m, Design{})
s.otherListButton(m)
}
func (s Table) TaskList(m *ice.Message, arg ...string) {
s.commonOtherList(m, Task{}).RenameAppend(model.STATUS, model.TASK_STATUS)
m.PushAction(s.Program)
}
func (s Table) CaseList(m *ice.Message, arg ...string) {
s.commonOtherList(m, Case{}).RenameAppend(model.STATUS, model.CASE_STATUS)
m.PushAction(s.Preview)
}
func (s Table) NoteList(m *ice.Message, arg ...string) {
s.commonOtherList(m, Note{})
}
func (s Table) FileList(m *ice.Message, arg ...string) {
if s.commonOtherList(m, File{}); s.IsLeader(m) {
m.PushAction(s.Download)
}
}
func (s Table) MeetList(m *ice.Message, arg ...string) {
s.commonOtherList(m, Meet{})
m.PushAction(s.Preview)
}
func (s Table) DealList(m *ice.Message, arg ...string) {
s.commonOtherList(m, Deal{})
}
func (s Table) finishCheck(m *ice.Message, target ice.Any, name string, arg ...string) bool {
count := m.Cmd(target, s.Select, m.CommandKey()+"_uid = ? AND status != ? AND status != ? AND status != ?", m.Option(model.UID), IssueRejected, IssueFinish, IssueCancel).Length()
if m.WarnNotValid(count > 0, kit.Format("还有 %v 个未完成的%s", count, name)) {
return true
}
return false
}
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) {
if !s.IsLeader(m) {
msg := s.Select(m.Spawn(), m.OptionSimple(model.STORY_UID, model.UID)...)
if m.WarnNotRight(msg.Append(model.USER_UID) != m.Option(model.USER_UID)) {
return
}
}
s.Table.ChangeStatus(m, m.Option(model.STORY_UID), m.Option(model.UID), from, to, arg...)
s.RecordEventWithName(m, "")
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 }
func (s Tables) BeforeMigrate(m *ice.Message, arg ...string) {}
func NewPortal(userPlace gonganxitong.UserPlacer, place gonganxitong.Placer) Portal {
return Portal{Portal: guanlixitong.NewPortal(userPlace, place)}
}