正在显示
25 个修改的文件
包含
4782 行增加
和
0 行删除
addons/.htaccess
0 → 100644
1 | +deny from all |
addons/facrm/.addonrc
0 → 100644
1 | +{"files":["application\\admin\\controller\\facrm\\Achievement.php","application\\admin\\controller\\facrm\\analysis\\Achievement.php","application\\admin\\controller\\facrm\\analysis\\Admin.php","application\\admin\\controller\\facrm\\analysis\\Customer.php","application\\admin\\controller\\facrm\\analysis\\Ranking.php","application\\admin\\controller\\facrm\\apps\\Apps.php","application\\admin\\controller\\facrm\\apps\\Config.php","application\\admin\\controller\\facrm\\apps\\Email.php","application\\admin\\controller\\facrm\\apps\\Notice.php","application\\admin\\controller\\facrm\\apps\\Sms.php","application\\admin\\controller\\facrm\\apps\\Theme.php","application\\admin\\controller\\facrm\\Backlog.php","application\\admin\\controller\\facrm\\business\\Contacts.php","application\\admin\\controller\\facrm\\business\\Index.php","application\\admin\\controller\\facrm\\business\\Record.php","application\\admin\\controller\\facrm\\clues\\Index.php","application\\admin\\controller\\facrm\\clues\\Record.php","application\\admin\\controller\\facrm\\Common.php","application\\admin\\controller\\facrm\\contract\\Index.php","application\\admin\\controller\\facrm\\contract\\Plan.php","application\\admin\\controller\\facrm\\contract\\Receivables.php","application\\admin\\controller\\facrm\\customer\\Contacts.php","application\\admin\\controller\\facrm\\customer\\Index.php","application\\admin\\controller\\facrm\\customer\\Record.php","application\\admin\\controller\\facrm\\Dashboard.php","application\\admin\\controller\\facrm\\Fields.php","application\\admin\\controller\\facrm\\flow\\Index.php","application\\admin\\controller\\facrm\\flow\\Log.php","application\\admin\\controller\\facrm\\Invoice.php","application\\admin\\controller\\facrm\\Notices.php","application\\admin\\controller\\facrm\\Operatelog.php","application\\admin\\controller\\facrm\\product\\Product.php","application\\admin\\controller\\facrm\\product\\Type.php","application\\admin\\controller\\facrm\\product\\Unit.php","application\\admin\\controller\\facrm\\setting\\Cloudcall.php","application\\admin\\controller\\facrm\\setting\\Payonline.php","application\\admin\\controller\\facrm\\setting\\Syndata.php","application\\admin\\controller\\facrm\\setting\\Validate.php","application\\admin\\controller\\facrm\\Tag.php","application\\admin\\controller\\facrm\\Third.php","application\\admin\\controller\\facrm\\workweixin\\Contacts.php","application\\admin\\controller\\facrm\\workweixin\\Index.php","application\\admin\\controller\\facrm\\workweixin\\Users.php","application\\admin\\lang\\zh-cn\\facrm\\contract\\plan.php","application\\admin\\lang\\zh-cn\\facrm\\fields.php","application\\admin\\lang\\zh-cn\\facrm\\notices.php","application\\admin\\model\\facrm\\Achievement.php","application\\admin\\model\\facrm\\business\\Contacts.php","application\\admin\\model\\facrm\\business\\Product.php","application\\admin\\model\\facrm\\Business.php","application\\admin\\model\\facrm\\Cloudcall.php","application\\admin\\model\\facrm\\CloudcallLog.php","application\\admin\\model\\facrm\\Clues.php","application\\admin\\model\\facrm\\contract\\Plan.php","application\\admin\\model\\facrm\\contract\\Product.php","application\\admin\\model\\facrm\\contract\\Receivables.php","application\\admin\\model\\facrm\\Contract.php","application\\admin\\model\\facrm\\customer\\Contacts.php","application\\admin\\model\\facrm\\Customer.php","application\\admin\\model\\facrm\\Fields.php","application\\admin\\model\\facrm\\flow\\Log.php","application\\admin\\model\\facrm\\flow\\Step.php","application\\admin\\model\\facrm\\Flow.php","application\\admin\\model\\facrm\\Invoice.php","application\\admin\\model\\facrm\\Notices.php","application\\admin\\model\\facrm\\Operatelog.php","application\\admin\\model\\facrm\\product\\Product.php","application\\admin\\model\\facrm\\product\\Type.php","application\\admin\\model\\facrm\\product\\Unit.php","application\\admin\\model\\facrm\\qywx\\Contacts.php","application\\admin\\model\\facrm\\qywx\\User.php","application\\admin\\model\\facrm\\record\\Files.php","application\\admin\\model\\facrm\\Record.php","application\\admin\\model\\facrm\\Scene.php","application\\admin\\model\\facrm\\Setting.php","application\\admin\\model\\facrm\\Tag.php","application\\admin\\validate\\facrm\\Business.php","application\\admin\\validate\\facrm\\Clues.php","application\\admin\\validate\\facrm\\contract\\Receivables.php","application\\admin\\validate\\facrm\\Contract.php","application\\admin\\validate\\facrm\\customer\\Contacts.php","application\\admin\\validate\\facrm\\Customer.php","application\\admin\\validate\\facrm\\Fields.php","application\\admin\\validate\\facrm\\Invoice.php","application\\admin\\validate\\facrm\\Notices.php","application\\admin\\validate\\facrm\\product\\Product.php","application\\admin\\validate\\facrm\\product\\Type.php","application\\admin\\validate\\facrm\\product\\Unit.php","application\\admin\\validate\\facrm\\Record.php","application\\admin\\view\\facrm\\achievement\\batch_admin.html","application\\admin\\view\\facrm\\achievement\\batch_team.html","application\\admin\\view\\facrm\\achievement\\index.html","application\\admin\\view\\facrm\\analysis\\achievement\\groups.html","application\\admin\\view\\facrm\\analysis\\achievement\\source.html","application\\admin\\view\\facrm\\analysis\\admin\\achievement.html","application\\admin\\view\\facrm\\analysis\\admin\\index.html","application\\admin\\view\\facrm\\analysis\\admin\\record.html","application\\admin\\view\\facrm\\analysis\\customer\\index.html","application\\admin\\view\\facrm\\analysis\\customer\\industry.html","application\\admin\\view\\facrm\\analysis\\customer\\level.html","application\\admin\\view\\facrm\\analysis\\customer\\source.html","application\\admin\\view\\facrm\\analysis\\ranking\\contract.html","application\\admin\\view\\facrm\\apps\\apps\\add.html","application\\admin\\view\\facrm\\apps\\apps\\edit.html","application\\admin\\view\\facrm\\apps\\apps\\index.html","application\\admin\\view\\facrm\\apps\\apps\\workweixin.html","application\\admin\\view\\facrm\\apps\\email\\add.html","application\\admin\\view\\facrm\\apps\\email\\edit.html","application\\admin\\view\\facrm\\apps\\email\\index.html","application\\admin\\view\\facrm\\apps\\email\\send.html","application\\admin\\view\\facrm\\apps\\email\\sends.html","application\\admin\\view\\facrm\\apps\\notice\\dingding.html","application\\admin\\view\\facrm\\apps\\notice\\email.html","application\\admin\\view\\facrm\\apps\\notice\\index.html","application\\admin\\view\\facrm\\apps\\notice\\min.html","application\\admin\\view\\facrm\\apps\\notice\\mp.html","application\\admin\\view\\facrm\\apps\\notice\\wxwork.html","application\\admin\\view\\facrm\\apps\\sms\\add.html","application\\admin\\view\\facrm\\apps\\sms\\edit.html","application\\admin\\view\\facrm\\apps\\sms\\index.html","application\\admin\\view\\facrm\\apps\\sms\\send.html","application\\admin\\view\\facrm\\apps\\sms\\sends.html","application\\admin\\view\\facrm\\apps\\theme\\index.html","application\\admin\\view\\facrm\\backlog\\contract.html","application\\admin\\view\\facrm\\backlog\\index.html","application\\admin\\view\\facrm\\backlog\\invoice.html","application\\admin\\view\\facrm\\backlog\\receivables.html","application\\admin\\view\\facrm\\business\\contacts\\correlation.html","application\\admin\\view\\facrm\\business\\index\\add.html","application\\admin\\view\\facrm\\business\\index\\edit.html","application\\admin\\view\\facrm\\business\\index\\index.html","application\\admin\\view\\facrm\\business\\record\\add.html","application\\admin\\view\\facrm\\business\\record\\files.html","application\\admin\\view\\facrm\\business\\record\\index.html","application\\admin\\view\\facrm\\clues\\index\\add.html","application\\admin\\view\\facrm\\clues\\index\\common.html","application\\admin\\view\\facrm\\clues\\index\\divert.html","application\\admin\\view\\facrm\\clues\\index\\edit.html","application\\admin\\view\\facrm\\clues\\index\\import.html","application\\admin\\view\\facrm\\clues\\index\\index.html","application\\admin\\view\\facrm\\clues\\index\\recyclebin.html","application\\admin\\view\\facrm\\clues\\index\\transform.html","application\\admin\\view\\facrm\\clues\\record\\add.html","application\\admin\\view\\facrm\\clues\\record\\files.html","application\\admin\\view\\facrm\\clues\\record\\index.html","application\\admin\\view\\facrm\\common\\fields.html","application\\admin\\view\\facrm\\common\\fields_12_2.html","application\\admin\\view\\facrm\\common\\fields_4_12.html","application\\admin\\view\\facrm\\common\\fields_6_2.html","application\\admin\\view\\facrm\\common\\pages.html","application\\admin\\view\\facrm\\contract\\index\\add.html","application\\admin\\view\\facrm\\contract\\index\\change.html","application\\admin\\view\\facrm\\contract\\index\\detail.html","application\\admin\\view\\facrm\\contract\\index\\edit.html","application\\admin\\view\\facrm\\contract\\index\\index.html","application\\admin\\view\\facrm\\contract\\index\\payurl.html","application\\admin\\view\\facrm\\contract\\index\\print.html","application\\admin\\view\\facrm\\contract\\index\\recyclebin.html","application\\admin\\view\\facrm\\contract\\index\\selectbusiness.html","application\\admin\\view\\facrm\\contract\\plan\\add.html","application\\admin\\view\\facrm\\contract\\plan\\edit.html","application\\admin\\view\\facrm\\contract\\plan\\index.html","application\\admin\\view\\facrm\\contract\\receivables\\add.html","application\\admin\\view\\facrm\\contract\\receivables\\detail.html","application\\admin\\view\\facrm\\contract\\receivables\\edit.html","application\\admin\\view\\facrm\\contract\\receivables\\index.html","application\\admin\\view\\facrm\\contract\\receivables\\payurl.html","application\\admin\\view\\facrm\\contract\\receivables\\recyclebin.html","application\\admin\\view\\facrm\\contract\\receivables\\selectcontract.html","application\\admin\\view\\facrm\\customer\\contacts\\add.html","application\\admin\\view\\facrm\\customer\\contacts\\edit.html","application\\admin\\view\\facrm\\customer\\contacts\\index.html","application\\admin\\view\\facrm\\customer\\contacts\\recyclebin.html","application\\admin\\view\\facrm\\customer\\index\\add.html","application\\admin\\view\\facrm\\customer\\index\\common.html","application\\admin\\view\\facrm\\customer\\index\\deal.html","application\\admin\\view\\facrm\\customer\\index\\divert.html","application\\admin\\view\\facrm\\customer\\index\\diyorder.html","application\\admin\\view\\facrm\\customer\\index\\edit.html","application\\admin\\view\\facrm\\customer\\index\\import.html","application\\admin\\view\\facrm\\customer\\index\\index.html","application\\admin\\view\\facrm\\customer\\index\\merge.html","application\\admin\\view\\facrm\\customer\\index\\recover.html","application\\admin\\view\\facrm\\customer\\index\\recyclebin.html","application\\admin\\view\\facrm\\customer\\index\\reduplicate.html","application\\admin\\view\\facrm\\customer\\index\\share.html","application\\admin\\view\\facrm\\customer\\record\\add.html","application\\admin\\view\\facrm\\customer\\record\\calllog.html","application\\admin\\view\\facrm\\customer\\record\\files.html","application\\admin\\view\\facrm\\customer\\record\\index.html","application\\admin\\view\\facrm\\dashboard\\boss.html","application\\admin\\view\\facrm\\dashboard\\index.html","application\\admin\\view\\facrm\\fields\\add.html","application\\admin\\view\\facrm\\fields\\edit.html","application\\admin\\view\\facrm\\fields\\index.html","application\\admin\\view\\facrm\\flow\\index\\add.html","application\\admin\\view\\facrm\\flow\\index\\edit.html","application\\admin\\view\\facrm\\flow\\index\\index.html","application\\admin\\view\\facrm\\flow\\log\\index.html","application\\admin\\view\\facrm\\invoice\\add.html","application\\admin\\view\\facrm\\invoice\\edit.html","application\\admin\\view\\facrm\\invoice\\index.html","application\\admin\\view\\facrm\\invoice\\opener.html","application\\admin\\view\\facrm\\invoice\\recyclebin.html","application\\admin\\view\\facrm\\invoice\\setting.html","application\\admin\\view\\facrm\\notices\\index.html","application\\admin\\view\\facrm\\operatelog\\detail.html","application\\admin\\view\\facrm\\operatelog\\index.html","application\\admin\\view\\facrm\\product\\product\\add.html","application\\admin\\view\\facrm\\product\\product\\edit.html","application\\admin\\view\\facrm\\product\\product\\index.html","application\\admin\\view\\facrm\\product\\product\\recyclebin.html","application\\admin\\view\\facrm\\product\\type\\add.html","application\\admin\\view\\facrm\\product\\type\\edit.html","application\\admin\\view\\facrm\\product\\type\\index.html","application\\admin\\view\\facrm\\product\\type\\recyclebin.html","application\\admin\\view\\facrm\\product\\unit\\add.html","application\\admin\\view\\facrm\\product\\unit\\edit.html","application\\admin\\view\\facrm\\product\\unit\\index.html","application\\admin\\view\\facrm\\product\\unit\\recyclebin.html","application\\admin\\view\\facrm\\setting\\cloudcall\\fromexten.html","application\\admin\\view\\facrm\\setting\\cloudcall\\fromextenedit.html","application\\admin\\view\\facrm\\setting\\cloudcall\\index.html","application\\admin\\view\\facrm\\setting\\cloudcall\\log.html","application\\admin\\view\\facrm\\setting\\cloudcall\\logdetail.html","application\\admin\\view\\facrm\\setting\\cloudcall\\moor.html","application\\admin\\view\\facrm\\setting\\cloudcall\\mycall.html","application\\admin\\view\\facrm\\setting\\cloudcall\\statistics.html","application\\admin\\view\\facrm\\setting\\cloudcall\\tycc100.html","application\\admin\\view\\facrm\\setting\\payonline\\index.html","application\\admin\\view\\facrm\\setting\\syndata\\index.html","application\\admin\\view\\facrm\\setting\\syndata\\synuserset.html","application\\admin\\view\\facrm\\setting\\validate\\edit.html","application\\admin\\view\\facrm\\setting\\validate\\index.html","application\\admin\\view\\facrm\\workweixin\\contacts\\index.html","application\\admin\\view\\facrm\\workweixin\\index\\index.html","application\\admin\\view\\facrm\\workweixin\\users\\edit.html","application\\admin\\view\\facrm\\workweixin\\users\\index.html","public\\assets\\addons\\facrm\\css\\bootstrap-editable.css","public\\assets\\addons\\facrm\\css\\jquery.autocomplete.min.css","public\\assets\\addons\\facrm\\css\\jquery.tagsinput.min.css","public\\assets\\addons\\facrm\\css\\spinner.css","public\\assets\\addons\\facrm\\img\\business-active.png","public\\assets\\addons\\facrm\\img\\business.png","public\\assets\\addons\\facrm\\img\\clear.png","public\\assets\\addons\\facrm\\img\\client-active.png","public\\assets\\addons\\facrm\\img\\client.png","public\\assets\\addons\\facrm\\img\\clue-active.png","public\\assets\\addons\\facrm\\img\\clue.png","public\\assets\\addons\\facrm\\img\\colorful.png","public\\assets\\addons\\facrm\\img\\data-active.png","public\\assets\\addons\\facrm\\img\\data.png","public\\assets\\addons\\facrm\\img\\home-active.png","public\\assets\\addons\\facrm\\img\\home.png","public\\assets\\addons\\facrm\\img\\loading.gif","public\\assets\\addons\\facrm\\img\\logo.png","public\\assets\\addons\\facrm\\img\\plus.png","public\\assets\\addons\\facrm\\img\\spinner.png","public\\assets\\addons\\facrm\\img\\statusbar.png","public\\assets\\addons\\facrm\\js\\bootstrap-editable.min.js","public\\assets\\addons\\facrm\\js\\china.js","public\\assets\\addons\\facrm\\js\\clipboard.min.js","public\\assets\\addons\\facrm\\js\\columntoggle.js","public\\assets\\addons\\facrm\\js\\gzyechart.js","public\\assets\\addons\\facrm\\js\\jquery.autocomplete.js","public\\assets\\addons\\facrm\\js\\jquery.colorpicker.min.js","public\\assets\\addons\\facrm\\js\\jquery.spinner.js","public\\assets\\addons\\facrm\\js\\jquery.tagsinput.js","public\\assets\\js\\backend\\facrm\\achievement.js","public\\assets\\js\\backend\\facrm\\analysis\\achievement.js","public\\assets\\js\\backend\\facrm\\analysis\\admin.js","public\\assets\\js\\backend\\facrm\\analysis\\customer.js","public\\assets\\js\\backend\\facrm\\analysis\\ranking.js","public\\assets\\js\\backend\\facrm\\apps\\apps.js","public\\assets\\js\\backend\\facrm\\apps\\email.js","public\\assets\\js\\backend\\facrm\\apps\\notice.js","public\\assets\\js\\backend\\facrm\\apps\\sms.js","public\\assets\\js\\backend\\facrm\\apps\\theme.js","public\\assets\\js\\backend\\facrm\\backlog.js","public\\assets\\js\\backend\\facrm\\business\\contacts.js","public\\assets\\js\\backend\\facrm\\business\\index.js","public\\assets\\js\\backend\\facrm\\business\\record.js","public\\assets\\js\\backend\\facrm\\clues\\index.js","public\\assets\\js\\backend\\facrm\\clues\\record.js","public\\assets\\js\\backend\\facrm\\contract\\index.js","public\\assets\\js\\backend\\facrm\\contract\\plan.js","public\\assets\\js\\backend\\facrm\\contract\\receivables.js","public\\assets\\js\\backend\\facrm\\customer\\contacts.js","public\\assets\\js\\backend\\facrm\\customer\\index.js","public\\assets\\js\\backend\\facrm\\customer\\record.js","public\\assets\\js\\backend\\facrm\\dashboard.js","public\\assets\\js\\backend\\facrm\\fields.js","public\\assets\\js\\backend\\facrm\\flow\\index.js","public\\assets\\js\\backend\\facrm\\flow\\log.js","public\\assets\\js\\backend\\facrm\\invoice.js","public\\assets\\js\\backend\\facrm\\notices.js","public\\assets\\js\\backend\\facrm\\operatelog.js","public\\assets\\js\\backend\\facrm\\product\\product.js","public\\assets\\js\\backend\\facrm\\product\\type.js","public\\assets\\js\\backend\\facrm\\product\\unit.js","public\\assets\\js\\backend\\facrm\\setting\\cloudcall.js","public\\assets\\js\\backend\\facrm\\setting\\syndata.js","public\\assets\\js\\backend\\facrm\\setting\\validate.js","public\\assets\\js\\backend\\facrm\\workweixin\\contacts.js","public\\assets\\js\\backend\\facrm\\workweixin\\users.js","public\\facrm\\index.html","public\\facrm\\static\\first.png","public\\facrm\\static\\icon.png","public\\facrm\\static\\index.css","public\\facrm\\static\\js\\chunk-vendors.603006ac.js","public\\facrm\\static\\js\\index.ec8b14de.js","public\\facrm\\static\\js\\pages-backlog-check.b4a82bcc.js","public\\facrm\\static\\js\\pages-backlog-checkLog.c23f8625.js","public\\facrm\\static\\js\\pages-backlog-checkLog~pagesA-checkLog-index.c3ac522f.js","public\\facrm\\static\\js\\pages-backlog-check~pages-backlog-checkLog~pages-backlog-index~pages-backlog-list~pages-backlog-rece~c1e1db60.d0007608.js","public\\facrm\\static\\js\\pages-backlog-check~pages-backlog-list~pages-backlog-receivablesCheck~pages-business-addBusiness-ind~a39423a0.4394d373.js","public\\facrm\\static\\js\\pages-backlog-check~pages-backlog-receivablesCheck~pages-business-addBusiness-index~pages-business-a~8be8c46a.a73d244d.js","public\\facrm\\static\\js\\pages-backlog-check~pages-backlog-receivablesCheck~pages-business-addBusiness-index~pages-business-f~d206df56.e0e1e61c.js","public\\facrm\\static\\js\\pages-backlog-index.737ca6aa.js","public\\facrm\\static\\js\\pages-backlog-list.2140c0e5.js","public\\facrm\\static\\js\\pages-backlog-list~pages-client-customerDetails~pages-contract-list-index~pages-invoice-index~pages-~4c39e008.3595a3bc.js","public\\facrm\\static\\js\\pages-backlog-receivablesCheck.19f60493.js","public\\facrm\\static\\js\\pages-business-addBusiness-index.d3928cc4.js","public\\facrm\\static\\js\\pages-business-addBusiness-selectProduct.ff0cd654.js","public\\facrm\\static\\js\\pages-business-addBusiness-selectProduct~pages-contacts-relevance~pages-highSeas-index.d9c04874.js","public\\facrm\\static\\js\\pages-business-detail.4b414062.js","public\\facrm\\static\\js\\pages-business-detail~pages-business-filter~pages-business-followUp~pages-client-filter~pages-client~c521a678.c7c1599a.js","public\\facrm\\static\\js\\pages-business-filter.c7e88fd5.js","public\\facrm\\static\\js\\pages-business-followUp.0b4339a1.js","public\\facrm\\static\\js\\pages-business-index.198f2b20.js","public\\facrm\\static\\js\\pages-business-index~pages-check-index~pages-client-index~pages-clues-list~pages-contacts-list~pages~4442d0f0.112428ac.js","public\\facrm\\static\\js\\pages-business-index~pages-client-index~pages-clues-list~pages-index-index~pages-presentation-index.cc564d85.js","public\\facrm\\static\\js\\pages-check-index.5fe6dbdb.js","public\\facrm\\static\\js\\pages-client-clientSet-clientSet.8006a30f.js","public\\facrm\\static\\js\\pages-client-clientShare.ef632008.js","public\\facrm\\static\\js\\pages-client-customerDetails.9fa2a8ca.js","public\\facrm\\static\\js\\pages-client-deal.4982e646.js","public\\facrm\\static\\js\\pages-client-details-index.77bb2687.js","public\\facrm\\static\\js\\pages-client-filter.d1f5b65d.js","public\\facrm\\static\\js\\pages-client-followUp.3bae8b7c.js","public\\facrm\\static\\js\\pages-client-index.a6ece2b4.js","public\\facrm\\static\\js\\pages-clues-cluesDetails.739a094f.js","public\\facrm\\static\\js\\pages-clues-details.c3f6562f.js","public\\facrm\\static\\js\\pages-clues-filter.557fda28.js","public\\facrm\\static\\js\\pages-clues-followUp.f59a1b03.js","public\\facrm\\static\\js\\pages-clues-index.f0ae8aec.js","public\\facrm\\static\\js\\pages-clues-list.db49c3d9.js","public\\facrm\\static\\js\\pages-contacts-addPerson.0a33c286.js","public\\facrm\\static\\js\\pages-contacts-detail.5aa1af6e.js","public\\facrm\\static\\js\\pages-contacts-filter.0481b8dd.js","public\\facrm\\static\\js\\pages-contacts-list.e4b080df.js","public\\facrm\\static\\js\\pages-contacts-relevance.63273ba3.js","public\\facrm\\static\\js\\pages-contract-index.f4afc78d.js","public\\facrm\\static\\js\\pages-contract-list-index.6679e78f.js","public\\facrm\\static\\js\\pages-highSeas-index.5a91ead9.js","public\\facrm\\static\\js\\pages-index-filter.97c0d12d.js","public\\facrm\\static\\js\\pages-index-index.2faf72d9.js","public\\facrm\\static\\js\\pages-index-index~pages-presentation-index.f6772976.js","public\\facrm\\static\\js\\pages-invoice-apply.fa494271.js","public\\facrm\\static\\js\\pages-invoice-details.e708ca20.js","public\\facrm\\static\\js\\pages-invoice-index.85734240.js","public\\facrm\\static\\js\\pages-invoice-openInvoice.8f0f5ece.js","public\\facrm\\static\\js\\pages-login-apply.237108fc.js","public\\facrm\\static\\js\\pages-login-auth.f7974135.js","public\\facrm\\static\\js\\pages-login-clause.b3cb33f0.js","public\\facrm\\static\\js\\pages-login-index.aab18b40.js","public\\facrm\\static\\js\\pages-member-list.cf369a12.js","public\\facrm\\static\\js\\pages-member-setMember.ae0ca73f.js","public\\facrm\\static\\js\\pages-member-third.cadf06e3.js","public\\facrm\\static\\js\\pages-more-cloudCallSet.1dda9ab3.js","public\\facrm\\static\\js\\pages-more-index.06df51c7.js","public\\facrm\\static\\js\\pages-more-personalDetails.462c8689.js","public\\facrm\\static\\js\\pages-more-recycle.da6323f8.js","public\\facrm\\static\\js\\pages-more-shiftClue.16744b1a.js","public\\facrm\\static\\js\\pages-more-sign.749623dd.js","public\\facrm\\static\\js\\pages-more-subscribe.b1f3e6b1.js","public\\facrm\\static\\js\\pages-more-transfer.8f74b0d9.js","public\\facrm\\static\\js\\pages-performance-celeritySet.f50207d8.js","public\\facrm\\static\\js\\pages-performance-filter.5902575a.js","public\\facrm\\static\\js\\pages-performance-index.4d40c209.js","public\\facrm\\static\\js\\pages-presentation-filter.b001ad44.js","public\\facrm\\static\\js\\pages-presentation-index.d767020a.js","public\\facrm\\static\\js\\pages-product-classify-classify.b0ae76db.js","public\\facrm\\static\\js\\pages-product-list.d722031b.js","public\\facrm\\static\\js\\pages-product-setProduct.4b0f8a69.js","public\\facrm\\static\\js\\pages-receivables-index.7bd2cbdd.js","public\\facrm\\static\\js\\pages-receivables-list.82e7e04c.js","public\\facrm\\static\\js\\pages-receivables-manage.e655b413.js","public\\facrm\\static\\js\\pages-send-index.dfe4ee07.js","public\\facrm\\static\\js\\pagesA-checkLog-index.aca8e454.js","public\\facrm\\static\\js\\pagesA-checkLog-logDetails.fe698fc5.js","public\\facrm\\static\\js\\pagesA-followLog-list.693747b9.js","public\\facrm\\static\\js\\pagesA-plan-list.9c8c2eb1.js","public\\facrm\\static\\js\\pagesA-plan-manage.7b4952e5.js","public\\facrm\\static\\js\\pagesA-wxWork-index.464eb7c5.js","public\\facrm\\static\\second.png","public\\facrm\\static\\third.png","public\\facrm\\uni_modules\\qiun-data-charts\\static\\h5\\echarts.min.js"],"license":"extended","licenseto":"10789","licensekey":"TXCDVNcJflv8IyAW KT3sWyeUeR3CRmtiCKnjxg==","domains":["brocrm.com"],"licensecodes":[],"validations":["22f57669af8d22741d3f7fd83a12766f"],"menus":["facrm","facrm\/customer","facrm\/customer\/index","facrm\/customer\/index\/receive","facrm\/customer\/index\/index","facrm\/customer\/index\/add","facrm\/customer\/index\/edit","facrm\/customer\/index\/del","facrm\/customer\/index\/multi","facrm\/customer\/index\/discard","facrm\/customer\/index\/import","facrm\/customer\/index\/recyclebin","facrm\/customer\/index\/restore","facrm\/customer\/index\/destroy","facrm\/customer\/index\/contractlist","facrm\/customer\/index\/receivableslist","facrm\/customer\/index\/getimporttpl","facrm\/customer\/index\/divert","facrm\/customer\/index\/receivables","facrm\/customer\/index\/contract","facrm\/customer\/index\/detail","facrm\/customer\/index\/contractadd","facrm\/customer\/index\/merge","facrm\/customer\/index\/next","facrm\/customer\/index\/recover","facrm\/customer\/index\/share","facrm\/customer\/index\/sdel","facrm\/customer\/index\/deal","facrm\/customer\/index\/export","facrm\/customer\/contacts","facrm\/customer\/contacts\/index","facrm\/customer\/contacts\/add","facrm\/customer\/contacts\/edit","facrm\/customer\/contacts\/del","facrm\/customer\/contacts\/multi","facrm\/customer\/contacts\/recyclebin","facrm\/customer\/contacts\/destroy","facrm\/customer\/contacts\/restore","facrm\/customer\/record","facrm\/customer\/record\/index","facrm\/customer\/record\/add","facrm\/customer\/record\/edit","facrm\/customer\/record\/del","facrm\/customer\/record\/multi","facrm\/customer\/record\/files","facrm\/customer\/record\/calllog","facrm\/customer\/index\/common","facrm\/customer\/index\/reduplicate","facrm\/business","facrm\/business\/index","facrm\/business\/index\/index","facrm\/business\/index\/add","facrm\/business\/index\/edit","facrm\/business\/index\/del","facrm\/business\/index\/multi","facrm\/business\/index\/product","facrm\/business\/contacts","facrm\/business\/contacts\/index","facrm\/business\/contacts\/correlation","facrm\/business\/contacts\/add","facrm\/business\/contacts\/edit","facrm\/business\/contacts\/del","facrm\/business\/contacts\/multi","facrm\/business\/record","facrm\/business\/record\/index","facrm\/business\/record\/add","facrm\/business\/record\/del","facrm\/business\/record\/edit","facrm\/business\/record\/multi","facrm\/business\/record\/files","facrm\/product","facrm\/product\/product","facrm\/product\/product\/get_type_list","facrm\/product\/product\/get_type_prop","facrm\/product\/product\/get_unit_list","facrm\/product\/product\/index","facrm\/product\/product\/recyclebin","facrm\/product\/product\/add","facrm\/product\/product\/edit","facrm\/product\/product\/del","facrm\/product\/product\/destroy","facrm\/product\/product\/restore","facrm\/product\/product\/multi","facrm\/product\/product\/import","facrm\/product\/type","facrm\/product\/type\/index","facrm\/product\/type\/recyclebin","facrm\/product\/type\/add","facrm\/product\/type\/edit","facrm\/product\/type\/del","facrm\/product\/type\/destroy","facrm\/product\/type\/restore","facrm\/product\/type\/multi","facrm\/product\/unit","facrm\/product\/unit\/edit","facrm\/product\/unit\/index","facrm\/product\/unit\/recyclebin","facrm\/product\/unit\/add","facrm\/product\/unit\/del","facrm\/product\/unit\/destroy","facrm\/product\/unit\/restore","facrm\/product\/unit\/multi","facrm\/contract","facrm\/contract\/index","facrm\/contract\/index\/index","facrm\/contract\/index\/recyclebin","facrm\/contract\/index\/destroy","facrm\/contract\/index\/restore","facrm\/contract\/index\/add","facrm\/contract\/index\/del","facrm\/contract\/index\/multi","facrm\/contract\/index\/print","facrm\/contract\/index\/change","facrm\/contract\/receivables","facrm\/contract\/receivables\/index","facrm\/contract\/receivables\/add","facrm\/contract\/receivables\/edit","facrm\/contract\/receivables\/del","facrm\/contract\/receivables\/multi","facrm\/contract\/receivables\/selectcontract","facrm\/contract\/receivables\/detail","facrm\/contract\/receivables\/recyclebin","facrm\/contract\/receivables\/destroy","facrm\/contract\/receivables\/restore","facrm\/contract\/index\/lists","facrm\/contract\/index\/edit","facrm\/contract\/index\/selectbusiness","facrm\/contract\/index\/selectcontact","facrm\/contract\/index\/selectpage","facrm\/contract\/index\/detail","facrm\/contract\/index\/contractadd","facrm\/contract\/receivables\/lists","facrm\/contract\/receivables\/receivablesadd","facrm\/contract\/plan","facrm\/contract\/plan\/index","facrm\/contract\/plan\/add","facrm\/contract\/plan\/edit","facrm\/contract\/plan\/del","facrm\/contract\/plan\/multi","facrm\/flow","facrm\/flow\/index","facrm\/flow\/index\/index","facrm\/flow\/index\/add","facrm\/flow\/index\/edit","facrm\/flow\/index\/del","facrm\/flow\/index\/multi","facrm\/flow\/log","facrm\/flow\/log\/index","facrm\/flow\/log\/add","facrm\/flow\/log\/edit","facrm\/flow\/log\/del","facrm\/flow\/log\/multi","facrm\/achievement","facrm\/achievement\/index","facrm\/achievement\/admin","facrm\/achievement\/edit","facrm\/achievement\/aedit","facrm\/achievement\/batchteam","facrm\/achievement\/del","facrm\/achievement\/batchadmin","facrm\/achievement\/add","facrm\/achievement\/multi","facrm\/fields","facrm\/fields\/index","facrm\/fields\/add","facrm\/fields\/edit","facrm\/fields\/multi","facrm\/fields\/del","facrm\/apps\/apps","facrm\/apps\/index","facrm\/apps\/apps\/add","facrm\/apps\/apps\/edit","facrm\/apps\/apps\/del","facrm\/apps\/apps\/index","facrm\/apps\/apps\/multi","facrm\/setting\/syndata","facrm\/setting\/syndata\/index","facrm\/setting\/syndata\/synuserset","facrm\/setting\/syndata\/synuser","facrm\/setting\/syndata\/add","facrm\/setting\/syndata\/edit","facrm\/setting\/syndata\/del","facrm\/setting\/syndata\/multi","facrm\/workweixin","facrm\/apps\/apps\/workweixin","facrm\/workweixin\/contacts","facrm\/workweixin\/contacts\/index","facrm\/workweixin\/contacts\/syn","facrm\/workweixin\/contacts\/add","facrm\/workweixin\/contacts\/edit","facrm\/workweixin\/contacts\/del","facrm\/workweixin\/contacts\/multi","facrm\/workweixin\/users","facrm\/workweixin\/users\/index","facrm\/workweixin\/users\/syn","facrm\/workweixin\/users\/add","facrm\/workweixin\/users\/edit","facrm\/workweixin\/users\/del","facrm\/workweixin\/users\/multi","facrm\/apps","facrm\/apps\/email","facrm\/apps\/email\/index","facrm\/apps\/email\/add","facrm\/apps\/email\/edit","facrm\/apps\/email\/send","facrm\/apps\/email\/del","facrm\/apps\/email\/multi","facrm\/apps\/email\/sends","facrm\/apps\/sms","facrm\/apps\/sms\/index","facrm\/apps\/sms\/add","facrm\/apps\/sms\/edit","facrm\/apps\/sms\/send","facrm\/apps\/sms\/sends","facrm\/apps\/sms\/del","facrm\/apps\/sms\/multi","facrm\/apps\/notice","facrm\/apps\/notice\/index","facrm\/apps\/notice\/edit","facrm\/notices","facrm\/notices\/index","facrm\/notices\/add","facrm\/notices\/edit","facrm\/notices\/del","facrm\/notices\/multi","facrm\/apps\/config\/index","facrm\/setting\/validate","facrm\/setting\/validate\/index","facrm\/setting\/validate\/edit","facrm\/setting\/payonline\/index","facrm\/apps\/theme\/index","facrm\/backlog","facrm\/backlog\/index","facrm\/backblog\/index1","facrm\/team_customer\/add","facrm\/team_customer\/edit","facrm\/team_customer\/del","facrm\/team_customer\/multi","facrm\/backlog\/verify","facrm\/backlog\/add","facrm\/backlog\/edit","facrm\/backlog\/del","facrm\/backlog\/multi","facrm\/analysis","facrm\/analysis\/customer","facrm\/analysis\/customer\/level","facrm\/analysis\/customer\/source","facrm\/analysis\/customer\/index","facrm\/analysis\/customer\/industry","facrm\/analysis\/customer\/add","facrm\/analysis\/customer\/edit","facrm\/analysis\/customer\/del","facrm\/analysis\/customer\/multi","facrm\/analysis\/admin","facrm\/analysis\/admin\/index","facrm\/analysis\/admin\/record","facrm\/analysis\/admin\/add","facrm\/analysis\/admin\/edit","facrm\/analysis\/admin\/del","facrm\/analysis\/admin\/multi","facrm\/analysis\/admin\/achievement","facrm\/analysis\/ranking","facrm\/analysis\/ranking\/contract","facrm\/analysis\/ranking\/receivables","facrm\/analysis\/ranking\/record","facrm\/analysis\/ranking\/product","facrm\/analysis\/ranking\/addcustomer","facrm\/analysis\/ranking\/add","facrm\/analysis\/ranking\/edit","facrm\/analysis\/ranking\/del","facrm\/analysis\/ranking\/multi","facrm\/analysis\/ranking\/index","facrm\/analysis\/achievement\/source","facrm\/analysis\/achievement\/groups","facrm\/dashboard","facrm\/dashboard\/index","facrm\/dashboard\/add","facrm\/dashboard\/edit","facrm\/dashboard\/del","facrm\/dashboard\/multi","facrm\/clues","facrm\/clues\/index","facrm\/clues\/index\/index","facrm\/clues\/index\/add","facrm\/clues\/index\/edit","facrm\/clues\/index\/del","facrm\/clues\/index\/discard","facrm\/clues\/index\/receive","facrm\/clues\/index\/divert","facrm\/clues\/index\/transform","facrm\/clues\/index\/import","facrm\/clues\/index\/getimporttpl","facrm\/clues\/index\/multi","facrm\/clues\/index\/next","facrm\/clues\/index\/restore","facrm\/clues\/index\/destroy","facrm\/clues\/index\/recyclebin","facrm\/clues\/index\/common","facrm\/clues\/record","facrm\/clues\/record\/index","facrm\/clues\/record\/add","facrm\/clues\/record\/del","facrm\/clues\/record\/files","facrm\/clues\/record\/edit","facrm\/clues\/record\/multi","facrm\/clues\/record\/calllog","facrm\/setting\/cloudcall","facrm\/setting\/cloudcall\/index","facrm\/setting\/cloudcall\/logdetail","facrm\/setting\/cloudcall\/call","facrm\/setting\/cloudcall\/edit","facrm\/setting\/cloudcall\/fromexten","facrm\/setting\/cloudcall\/fromextenedit","facrm\/setting\/cloudcall\/fromextendel","facrm\/setting\/cloudcall\/log","facrm\/setting\/cloudcall\/statistics","facrm\/invoice","facrm\/invoice\/index","facrm\/invoice\/add","facrm\/invoice\/edit","facrm\/invoice\/del","facrm\/invoice\/lists","facrm\/invoice\/recyclebin","facrm\/invoice\/destroy","facrm\/invoice\/restore","facrm\/invoice\/setting","facrm\/invoice\/opener","facrm\/invoice\/multi","facrm\/operatelog","facrm\/operatelog\/index","facrm\/operatelog\/del","facrm\/operatelog\/detail"]} |
addons/facrm/Facrm.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm; | ||
4 | + | ||
5 | + | ||
6 | +use app\admin\model\facrm\Contract; | ||
7 | +use app\common\library\Menu; | ||
8 | +use fast\Tree; | ||
9 | +use think\Addons; | ||
10 | +use think\Db; | ||
11 | +use think\Exception; | ||
12 | +use think\exception\PDOException; | ||
13 | +use think\exception\ValidateException; | ||
14 | +use think\Queue; | ||
15 | +use think\Cookie; | ||
16 | + | ||
17 | +/** | ||
18 | + * 插件 | ||
19 | + */ | ||
20 | +class Facrm extends Addons | ||
21 | +{ | ||
22 | + | ||
23 | + /** | ||
24 | + * 插件安装方法 | ||
25 | + * @return bool | ||
26 | + */ | ||
27 | + public function install() | ||
28 | + { | ||
29 | + $menu = []; | ||
30 | + $config_file = ADDON_PATH . "facrm" . DS . 'config' . DS . "menu.php"; | ||
31 | + if (is_file($config_file)) { | ||
32 | + $menu = include $config_file; | ||
33 | + } | ||
34 | + if ($menu) { | ||
35 | + Menu::create($menu); | ||
36 | + } | ||
37 | + /** | ||
38 | + * 增加手机号字段 | ||
39 | + */ | ||
40 | + $database=config('database'); | ||
41 | + $isexits=Db::query("SELECT 1 FROM information_schema.COLUMNS WHERE table_name='{$database['prefix']}admin' AND COLUMN_NAME='mobile' limit 1"); | ||
42 | + if (!$isexits){ | ||
43 | + Db::query("ALTER TABLE {$database['prefix']}admin ADD mobile VARCHAR(20) NULL COMMENT '手机'"); | ||
44 | + } | ||
45 | + | ||
46 | + //首次安装创建表并导入测试数据 | ||
47 | + \think\addons\Service::importsql('facrm'); | ||
48 | + if (version_compare(config('fastadmin.version'), '1.3.0', '<') && Db::name("facrm_customer")->count() == 0) { | ||
49 | + $this->importData('testdata',''); | ||
50 | + } | ||
51 | + return true; | ||
52 | + } | ||
53 | + | ||
54 | + /** | ||
55 | + * 插件卸载方法 | ||
56 | + * @return bool | ||
57 | + */ | ||
58 | + public function uninstall() | ||
59 | + { | ||
60 | + $info = get_addon_info('facrm'); | ||
61 | + Menu::delete(isset($info['first_menu']) ? $info['first_menu'] : 'facrm'); | ||
62 | + return true; | ||
63 | + } | ||
64 | + | ||
65 | + /** | ||
66 | + * 插件启用方法 | ||
67 | + */ | ||
68 | + public function enable() | ||
69 | + { | ||
70 | + $info = get_addon_info('facrm'); | ||
71 | + Menu::enable(isset($info['first_menu']) ? $info['first_menu'] : 'facrm'); | ||
72 | + } | ||
73 | + | ||
74 | + /** | ||
75 | + * 插件禁用方法 | ||
76 | + */ | ||
77 | + public function disable() | ||
78 | + { | ||
79 | + $info = get_addon_info('facrm'); | ||
80 | + Menu::disable(isset($info['first_menu']) ? $info['first_menu'] : 'facrm'); | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * 插件升级方法 | ||
85 | + */ | ||
86 | + public function upgrade() | ||
87 | + { | ||
88 | + $menu = include ADDON_PATH . 'facrm' . DS . 'config' . DS . 'menu.php'; | ||
89 | + Menu::upgrade('facrm', $menu); | ||
90 | + /** | ||
91 | + * 增加手机号字段 | ||
92 | + */ | ||
93 | + $database=config('database'); | ||
94 | + $isexits=Db::query("SELECT 1 FROM information_schema.COLUMNS WHERE table_name='{$database['prefix']}admin' AND COLUMN_NAME='mobile' limit 1"); | ||
95 | + if (!$isexits){ | ||
96 | + Db::query("ALTER TABLE {$database['prefix']}admin ADD mobile VARCHAR(20) NULL COMMENT '手机'"); | ||
97 | + } | ||
98 | + } | ||
99 | + | ||
100 | + /** | ||
101 | + * 登录后 不跟进和未成交的客户处理 | ||
102 | + */ | ||
103 | + public function adminLoginInit() | ||
104 | + { | ||
105 | + $config = $this->getConfig(); | ||
106 | + //不跟进 lose_day1 //不成交lose_day2 | ||
107 | + | ||
108 | + if ($config['lose_day1'] > 0 || ($config['lose_day2'] > 0)) { | ||
109 | + $customerModel = model('\app\admin\model\facrm\Customer'); | ||
110 | + $customerModel->where('deal_status', 0)->where('owner_user_id', 'gt', 0); | ||
111 | + | ||
112 | + if ($config['lose_day1'] > 0 && $config['lose_day2'] > 0) { | ||
113 | + //如果不跟进和不成交都开启,掉入公海逻辑 | ||
114 | + $customerModel->where(function ($query) use ($config) { | ||
115 | + $query->where('follow_time', '<', (time() - $config['lose_day1'] * 86400))->where('follow_time', 'gt', 0)->whereOr('collect_time', '<', (time() - $config['lose_day2'] * 86400)); | ||
116 | + }); | ||
117 | + } elseif ($config['lose_day1'] > 0 && ($config['lose_day2'] <= 0)) { | ||
118 | + //如果只开启不跟进,掉入公海逻辑 | ||
119 | + $customerModel->where('follow_time', '<', (time() - $config['lose_day1'] * 86400))->where('follow_time', 'gt', 0); | ||
120 | + } elseif ($config['lose_day1'] <= 0 && $config['lose_day2'] > 0) { | ||
121 | + //如果只开启不成交,掉入公海逻辑 | ||
122 | + $customerModel->where('collect_time', '<', (time() - $config['lose_day2'] * 86400)); | ||
123 | + } else { | ||
124 | + return true; | ||
125 | + } | ||
126 | + | ||
127 | + $lists = $customerModel->fetchSql(false)->select(); | ||
128 | + if ($lists) { | ||
129 | + foreach ($lists as $row) { | ||
130 | + $owner_user_id = $row->owner_user_id; | ||
131 | + $row->discard(); | ||
132 | + \app\admin\model\AdminLog::create([ | ||
133 | + 'title' => __("客户过期自动加入公海"), | ||
134 | + 'content' => json_encode(['id' => $row->id, 'name' => $row->name], JSON_UNESCAPED_UNICODE), | ||
135 | + 'url' => "customer/discard", | ||
136 | + 'admin_id' => $owner_user_id, | ||
137 | + ]); | ||
138 | + } | ||
139 | + } | ||
140 | + } | ||
141 | + } | ||
142 | + | ||
143 | + | ||
144 | + /** | ||
145 | + * 登录后 | ||
146 | + */ | ||
147 | + public function adminLoginAfter($request){ | ||
148 | + | ||
149 | + $exten_type=$request->request('exten_type',''); | ||
150 | + $from_exten=$request->request('from_exten','','htmlentities');//工号 | ||
151 | + \think\Cookie::set("facrm_extentype", $exten_type?$exten_type:'',86400 * 7);//云呼通话方式 | ||
152 | + Cookie::set("facrm_from_exten", $from_exten?$from_exten:'',86400 * 7); | ||
153 | + if($from_exten){ | ||
154 | + \app\admin\model\facrm\Cloudcall::edit('','',$from_exten,true); | ||
155 | + } | ||
156 | + | ||
157 | + } | ||
158 | + | ||
159 | + | ||
160 | + /** | ||
161 | + * 审核成功钩子 | ||
162 | + * @param $param | ||
163 | + */ | ||
164 | + public function facrmFlowVerify(&$param) | ||
165 | + { | ||
166 | + if (!isset($param['types'])) return false; | ||
167 | + $check_status=($param['is_end'] == 1&&$param['status']==1)?2:(($param['status']==0)?3:1); | ||
168 | + switch ($param['types']) { | ||
169 | + case 'receivables': | ||
170 | + if ($param['is_end'] == 1 && $param['status'] == 1) { | ||
171 | + $receivablesModel = new \app\admin\model\facrm\contract\Receivables(); | ||
172 | + //$contractModel=new \app\admin\model\facrm\Contract(); | ||
173 | + $receivables = $receivablesModel::get($param['types_id']); | ||
174 | + $receivables->contract()->setInc('return_money', $receivables->money); | ||
175 | + $receivables->plan()->update(['status'=>2,'return_money'=>\think\Db::raw("`return_money`+{$receivables['money']}")]); | ||
176 | + } | ||
177 | + //1审核中、2审核通过、3审核未通过 | ||
178 | + break; | ||
179 | + case "contract": | ||
180 | + | ||
181 | + if ($param['is_end'] == 1 && $param['status'] == 1) { | ||
182 | + $contractModel = new \app\admin\model\facrm\Contract(); | ||
183 | + $contract = $contractModel::get($param['types_id']); | ||
184 | + | ||
185 | + $contract->customer()->update([ | ||
186 | + 'deal_status' => 1, 'deal_time' => time(), | ||
187 | + 'purchase_times'=> Db::raw('purchase_times+1'), | ||
188 | + 'purchase_total'=> Db::raw('purchase_total+'.$contract->money), | ||
189 | + ]); | ||
190 | + | ||
191 | + //如果有商机也改成成交状态 | ||
192 | + if ($contract->business_id) { | ||
193 | + $contract->business()->update(['is_end' => 1, 'deal_time' => time()]);//把商机改成成交状态 | ||
194 | + } | ||
195 | + | ||
196 | + } | ||
197 | + break; | ||
198 | + default: | ||
199 | + | ||
200 | + } | ||
201 | + //消息通知 | ||
202 | + try { | ||
203 | + Queue::push("addons\\facrm\\library\\notice\queue\\Flow" . ucfirst($param['types']) . "Job", | ||
204 | + ['model_id' => $param['types_id'], 'data' => ['check_status' => $check_status]]); | ||
205 | + } catch (\Exception $e) { | ||
206 | + | ||
207 | + } | ||
208 | + //消息通知end | ||
209 | + | ||
210 | + return true; | ||
211 | + | ||
212 | + } | ||
213 | + | ||
214 | + /** | ||
215 | + * 用户注册成功钩子 | ||
216 | + */ | ||
217 | + public function userRegisterSuccessed(&$user) | ||
218 | + { | ||
219 | + return \addons\facrm\library\Helper::synUser($user); | ||
220 | + } | ||
221 | + | ||
222 | + /** | ||
223 | + * 发送邮件成功钩子 | ||
224 | + *param_data types类型如customer,contacts| typesid对应的ID | ||
225 | + *send_data发送邮件的内容 | ||
226 | + *types_data 当前对象的数据 | ||
227 | + * @param $param | ||
228 | + */ | ||
229 | + public function facrmSendEmailSuccess($param) | ||
230 | + { | ||
231 | + if (!isset($param['param_data']) || !$param['param_data'] || !isset($param['send_data']) || !$param['send_data']) return false; | ||
232 | + return $this->addRecord($param['param_data'], $param['send_data'], __("发送邮件")); | ||
233 | + } | ||
234 | + | ||
235 | + | ||
236 | + /** | ||
237 | + * 发送短息成功钩子 | ||
238 | + *param_data types类型如customer,contacts| typesid对应的ID | ||
239 | + *send_data发送短息的内容 | ||
240 | + *types_data 当前对象的数据 | ||
241 | + * @param $param | ||
242 | + */ | ||
243 | + public function facrmSendSmsSuccess($param) | ||
244 | + { | ||
245 | + if (!isset($param['param_data']) || !$param['param_data'] || !isset($param['send_data']) || !$param['send_data']) return false; | ||
246 | + return $this->addRecord($param['param_data'], $param['send_data'], __("发送短息")); | ||
247 | + } | ||
248 | + | ||
249 | + /** | ||
250 | + * 自动添加跟进 | ||
251 | + * @param $param_data | ||
252 | + * @param $send_data | ||
253 | + * @param string $df_content | ||
254 | + * @return bool | ||
255 | + * @throws \think\exception\DbException | ||
256 | + */ | ||
257 | + private function addRecord($param_data, $send_data, $df_content = "") | ||
258 | + { | ||
259 | + $result = false; | ||
260 | + $record_data = array(); | ||
261 | + if ($param_data && $param_data['types']) { | ||
262 | + switch ($param_data['types']) { | ||
263 | + case "customer": | ||
264 | + //跟进客户 | ||
265 | + $customer = model('\app\admin\model\facrm\Customer'); | ||
266 | + $rowc = $customer->get($param_data['typesid']); | ||
267 | + if (!$rowc) return false; | ||
268 | + $rowc->follow_time = time(); | ||
269 | + $rowc->save(); | ||
270 | + $record_data['types'] = "customer"; | ||
271 | + $record_data['types_id'] = $rowc->id; | ||
272 | + break; | ||
273 | + case "business": | ||
274 | + $business = model('\app\admin\model\facrm\Business'); | ||
275 | + $row = $business->get($param_data['typesid']); | ||
276 | + if (!$row) return false; | ||
277 | + //更新客户表 | ||
278 | + $row->customer()->update(["follow_time" => time()]); | ||
279 | + $row->save(); | ||
280 | + $record_data['types'] = "business"; | ||
281 | + $record_data['types_id'] = $row->id; | ||
282 | + break; | ||
283 | + case "contacts": | ||
284 | + //跟进客户 | ||
285 | + $contactsModel = model('\app\admin\model\facrm\customer\Contacts'); | ||
286 | + $contacts = $contactsModel->get($param_data['typesid']); | ||
287 | + if (!$contacts || !$contacts->customer) return false; | ||
288 | + $contacts->customer->follow_time = time(); | ||
289 | + $contacts->customer->save(); | ||
290 | + $record_data['types'] = "customer"; | ||
291 | + $record_data['types_id'] = $contacts->customer_id; | ||
292 | + $send_data['content']=(isset($send_data['content']) ? $send_data['content'] : $df_content)."【联系人:{$contacts['name']}】"; | ||
293 | + break; | ||
294 | + case "clues": | ||
295 | + //跟进线索 | ||
296 | + $cluesModel = model('\app\admin\model\facrm\Clues'); | ||
297 | + $rowc = $cluesModel->get($param_data['typesid']); | ||
298 | + if (!$rowc) return false; | ||
299 | + $rowc->follow_time = time(); | ||
300 | + $rowc->save(); | ||
301 | + $record_data['types'] = "clues"; | ||
302 | + $record_data['types_id'] = $rowc->id; | ||
303 | + break; | ||
304 | + default: | ||
305 | + break; | ||
306 | + } | ||
307 | + } | ||
308 | + if ($record_data) { | ||
309 | + (new \app\admin\model\facrm\Record)->allowField(true)->save(array_merge($record_data, [ | ||
310 | + 'content' => strip_tags(isset($send_data['content']) ? $send_data['content'] : $df_content), | ||
311 | + 'record_type' => isset($send_data['record_type']) ? $send_data['record_type'] : 0,//跟进类型 | ||
312 | + 'create_user_id' => isset($send_data['create_user_id']) ? $send_data['create_user_id'] : 0, | ||
313 | + ])); | ||
314 | + } | ||
315 | + return $result; | ||
316 | + } | ||
317 | + | ||
318 | + /** | ||
319 | + * 导入数据 | ||
320 | + */ | ||
321 | + protected function importData($sqlname="",$dir='config') | ||
322 | + { | ||
323 | + $sqlFile = ADDON_PATH . 'facrm' . ($dir?DS.$dir:'').DS .$sqlname.'.sql'; | ||
324 | + | ||
325 | + if (is_file($sqlFile)) { | ||
326 | + $lines = file($sqlFile); | ||
327 | + $templine = ''; | ||
328 | + foreach ($lines as $line) { | ||
329 | + if (substr($line, 0, 2) == '--' || $line == '' || substr($line, 0, 2) == '/*') { | ||
330 | + continue; | ||
331 | + } | ||
332 | + | ||
333 | + $templine .= $line; | ||
334 | + if (substr(trim($line), -1, 1) == ';') { | ||
335 | + $templine = str_ireplace('__PREFIX__', config('database.prefix'), $templine); | ||
336 | + $templine = str_ireplace('INSERT INTO ', 'INSERT IGNORE INTO ', $templine); | ||
337 | + try { | ||
338 | + Db::getPdo()->exec($templine); | ||
339 | + } catch (\Exception $e) { | ||
340 | + echo $e->getMessage(); | ||
341 | + } | ||
342 | + $templine = ''; | ||
343 | + } | ||
344 | + } | ||
345 | + } | ||
346 | + } | ||
347 | + | ||
348 | + /** | ||
349 | + * 手机号脚本替换 | ||
350 | + */ | ||
351 | + public function viewFilter(& $content) | ||
352 | + { | ||
353 | + $module = strtolower(request()->module()); | ||
354 | + $controller=strtolower(request()->controller()); | ||
355 | + $action=strtolower(request()->action()); | ||
356 | + if ($module == 'admin'&&$controller=='auth.admin'&&version_compare(config('fastadmin.version'), '1.3.4', '<')) { | ||
357 | + $view=\think\View::instance(); | ||
358 | + $mobile=isset($view->row->mobile)?$view->row->mobile:''; | ||
359 | + $str_rp='<div class="form-group hidden layer-footer">'; | ||
360 | + $new_rp='<div class="form-group"><label for="mobile" class="control-label col-xs-12 col-sm-2">手机:</label><div class="col-xs-12 col-sm-8"><input type="mobile" class="form-control" id="mobile" name="row[mobile]" value="'.$mobile.'" /></div></div>'; | ||
361 | + $content = preg_replace_callback("/{$str_rp}/i", function ($matches) use ($new_rp,$str_rp){ | ||
362 | + return $new_rp.$str_rp; | ||
363 | + }, $content); | ||
364 | + } | ||
365 | + if ($module == 'admin'&&$controller=='index'&&$action=='index') { | ||
366 | + $view=\think\View::instance(); | ||
367 | + if (!isset($view->auth)) return true; | ||
368 | + //获取合同\,回款待审批 | ||
369 | + $contractModel= new Contract(); | ||
370 | + $receivablesModel=new \app\admin\model\facrm\contract\Receivables(); | ||
371 | + $invoiceModel=new \app\admin\model\facrm\Invoice(); | ||
372 | + | ||
373 | + | ||
374 | + $filter_w['check_status'] =['in',[0,1]]; | ||
375 | + $total = $contractModel->where($filter_w)->where('','exp','FIND_IN_SET('. $view->auth->id.',flow_admin_id)')->fetchSql(false)->count(); | ||
376 | + $total +=$receivablesModel->where($filter_w)->where('','exp','FIND_IN_SET('.$view->auth->id.',flow_admin_id)')->fetchSql(false)->count(); | ||
377 | + $total +=$invoiceModel->where($filter_w)->where('','exp','FIND_IN_SET('.$view->auth->id.',flow_admin_id)')->fetchSql(false)->count(); | ||
378 | + | ||
379 | + | ||
380 | + $content =$content."<script>function setsidebar(){Backend.api.sidebar({'facrm/backlog':{$total},'facrm':{$total}})}; setTimeout('setsidebar()','5000');</script>"; | ||
381 | + } | ||
382 | + //云呼方式 | ||
383 | + if ($module == 'admin'&&$controller=='index'&&$action=='login') { | ||
384 | + //获取云呼配置 | ||
385 | + $all_types = \addons\facrm\library\cloudcall\Call::getProviders(); | ||
386 | + $keys = ""; | ||
387 | + foreach ($all_types as $v) { | ||
388 | + $keys .= $keys ? ',' .'cloudcall'. $v : 'cloudcall' . $v; | ||
389 | + } | ||
390 | + $settingModel = new \app\admin\model\facrm\Setting(); | ||
391 | + $setting= $settingModel->where('key', 'in', $keys)->where('status', 1)->find();//只找一条云呼通道 | ||
392 | + if (!$setting) return true; | ||
393 | + $setting=$setting['values']; | ||
394 | + | ||
395 | + $exten_type=Cookie::get("facrm_extentype");//云呼通话方式 | ||
396 | + $from_exten=htmlentities(Cookie::get("facrm_from_exten"));//云呼通话坐席工号 | ||
397 | + $str_rp='<div class="form-group checkbox">'; | ||
398 | + $new_rp=""; | ||
399 | + if (isset($setting['open_exten'])&&$setting['open_exten']){ | ||
400 | + $new_rp=' <div class="input-group"> | ||
401 | + <div class="input-group-addon"><span class="glyphicon fa fa-phone" aria-hidden="true"></span></div> | ||
402 | + <input type="text" class="form-control" placeholder="云呼工号,如不知道可留空" name="from_exten" value="'.$from_exten.'" /> | ||
403 | + </div>'; | ||
404 | + } | ||
405 | + | ||
406 | + $new_rp.=' <div class="input-group"> | ||
407 | + <div class="input-group-addon"><span class="glyphicon fa fa-phone" aria-hidden="true"></span></div> | ||
408 | + <select class="form-control selectpicker" name="exten_type"><option value=""> 请选择云呼方式</option> | ||
409 | + <option value="Local" '.($exten_type=='Local'?'selected':'').'>工作手机</option> | ||
410 | + <option value="sip" '.($exten_type=='sip'?'selected':'').'>软电话</option> | ||
411 | + <option value="gateway" '.($exten_type=='gateway'?'selected':'').'>话机方式</option> | ||
412 | + </select> | ||
413 | + </div>'; | ||
414 | + $content = preg_replace_callback("/{$str_rp}/i", function ($matches) use ($new_rp,$str_rp){ | ||
415 | + return $new_rp.$str_rp; | ||
416 | + }, $content); | ||
417 | + } | ||
418 | + } | ||
419 | + | ||
420 | + /** | ||
421 | + * 发票开具钩子 | ||
422 | + * @param $param | ||
423 | + */ | ||
424 | + public function facrmInvoiceOpener($param){ | ||
425 | + //通知 | ||
426 | + Queue::push("addons\\facrm\\library\\notice\queue\\InvoiceJob", [ | ||
427 | + 'model_id'=>$param['id'], | ||
428 | + ]); | ||
429 | + } | ||
430 | +} |
addons/facrm/config.html
0 → 100644
1 | +{php} | ||
2 | +$ignore=[ | ||
3 | + 'diy_text','deal_status','deal_time','is_lock', | ||
4 | + 'level','industry','tags','source',"id", | ||
5 | + 'create_user_id','owner_user_id','user_id','ro_user_id', | ||
6 | + 'rw_user_id','province','city','area', | ||
7 | + 'lng','lat','city','next_time', | ||
8 | +]; | ||
9 | +$customer_fields=\addons\facrm\library\Helper::getfield('customer','*',['infinity'=>__("不限制唯一字段")],$ignore); | ||
10 | +{/php} | ||
11 | + | ||
12 | + | ||
13 | +<form id="config-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action=""> | ||
14 | + {if $addon.tips} | ||
15 | + <div class="alert {$addon.tips.extend|default='alert-info-light'}" style="margin-bottom:10px;"> | ||
16 | + <b>{$addon.tips.title|htmlentities}</b><br> | ||
17 | + {$addon.tips.value|htmlentities} | ||
18 | + </div> | ||
19 | + {/if} | ||
20 | + <table class="table table-striped"> | ||
21 | + <thead> | ||
22 | + <tr> | ||
23 | + <th width="15%">{:__('Title')}</th> | ||
24 | + <th width="85%">{:__('Value')}</th> | ||
25 | + </tr> | ||
26 | + </thead> | ||
27 | + <tbody> | ||
28 | + {foreach $addon.config as $item} | ||
29 | + <tr> | ||
30 | + <td>{$item.title|htmlentities}</td> | ||
31 | + <td> | ||
32 | + <div class="row"> | ||
33 | + <div class="col-sm-8 col-xs-12"> | ||
34 | + {switch $item.type} | ||
35 | + {case string} | ||
36 | + <input {$item.extend|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule|htmlentities}" data-tip="{$item.tip|htmlentities}"/> | ||
37 | + {/case} | ||
38 | + {case text} | ||
39 | + <textarea {$item.extend|htmlentities} name="row[{$item.name|htmlentities}]" class="form-control" data-rule="{$item.rule|htmlentities}" rows="5" data-tip="{$item.tip|htmlentities}">{$item.value|htmlentities}</textarea> | ||
40 | + {/case} | ||
41 | + {case array} | ||
42 | + <dl class="fieldlist" data-name="row[{$item.name|htmlentities}]"> | ||
43 | + <dd> | ||
44 | + <ins>{:__('键')}</ins> | ||
45 | + <ins>{:__('值')}</ins> | ||
46 | + </dd> | ||
47 | + <dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd> | ||
48 | + <textarea name="row[{$item.name|htmlentities}]" cols="30" rows="5" class="hide">{$item.value|json_encode|htmlentities}</textarea> | ||
49 | + </dl> | ||
50 | + {/case} | ||
51 | + {case date} | ||
52 | + <input {$item.extend|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/> | ||
53 | + {/case} | ||
54 | + {case time} | ||
55 | + <input {$item.extend|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/> | ||
56 | + {/case} | ||
57 | + {case datetime} | ||
58 | + <input {$item.extend|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/> | ||
59 | + {/case} | ||
60 | + {case number} | ||
61 | + <input {$item.extend|htmlentities} type="number" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/> | ||
62 | + {/case} | ||
63 | + {case checkbox} | ||
64 | + {foreach name="item.content" item="vo"} | ||
65 | + <label for="row[{$item.name|htmlentities}][]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}][]-{$key|htmlentities}" name="row[{$item.name|htmlentities}][]" type="checkbox" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label> | ||
66 | + {/foreach} | ||
67 | + {/case} | ||
68 | + {case radio} | ||
69 | + {foreach name="item.content" item="vo"} | ||
70 | + <label for="row[{$item.name|htmlentities}]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}]-{$key|htmlentities}" name="row[{$item.name|htmlentities}]" type="radio" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label> | ||
71 | + {/foreach} | ||
72 | + {/case} | ||
73 | + {case value="select" break="0"}{/case} | ||
74 | + {case value="selects"} | ||
75 | + {php} | ||
76 | + if($item['name']==='unique'){ | ||
77 | + $item['content']=$customer_fields; | ||
78 | + } | ||
79 | + | ||
80 | + {/php} | ||
81 | + <select {$item.extend|htmlentities} name="row[{$item.name|htmlentities}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip|htmlentities}" {$item.type=='selects'?'multiple':''}> | ||
82 | + {foreach name="item.content" item="vo"} | ||
83 | + <option value="{$key|htmlentities}" {in name="key" value="$item.value" }selected{/in}>{$vo|htmlentities}</option> | ||
84 | + {/foreach} | ||
85 | + </select> | ||
86 | + {/case} | ||
87 | + {case value="image" break="0"}{/case} | ||
88 | + {case value="images"} | ||
89 | + <div class="input-group"> | ||
90 | + <input {$item.extend|htmlentities} id="c-{$item.name|htmlentities}" class="form-control" size="50" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"> | ||
91 | + <div class="input-group-addon no-border no-padding"> | ||
92 | + <span><button type="button" id="faupload-{$item.name|htmlentities}" class="btn btn-danger faupload" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name|htmlentities}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span> | ||
93 | + <span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span> | ||
94 | + </div> | ||
95 | + <span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span> | ||
96 | + </div> | ||
97 | + <ul class="row list-inline faupload-preview" id="p-{$item.name|htmlentities}"></ul> | ||
98 | + {/case} | ||
99 | + {case value="file" break="0"}{/case} | ||
100 | + {case value="files"} | ||
101 | + <div class="input-group"> | ||
102 | + <input {$item.extend|htmlentities} id="c-{$item.name|htmlentities}" class="form-control" size="50" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"> | ||
103 | + <div class="input-group-addon no-border no-padding"> | ||
104 | + <span><button type="button" id="faupload-{$item.name|htmlentities}" class="btn btn-danger faupload" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}" data-preview-id="p-{$item.name|htmlentities}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span> | ||
105 | + <span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span> | ||
106 | + </div> | ||
107 | + <span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span> | ||
108 | + </div> | ||
109 | + <ul class="row list-inline faupload-preview" id="p-{$item.name|htmlentities}"></ul> | ||
110 | + {/case} | ||
111 | + {case bool} | ||
112 | + <label for="row[{$item.name|htmlentities}]-yes"><input id="row[{$item.name|htmlentities}]-yes" name="row[{$item.name|htmlentities}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip|htmlentities}" /> {:__('Yes')}</label> | ||
113 | + <label for="row[{$item.name|htmlentities}]-no"><input id="row[{$item.name|htmlentities}]-no" name="row[{$item.name|htmlentities}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip|htmlentities}" /> {:__('No')}</label> | ||
114 | + {/case} | ||
115 | + {default /}{$item.value|htmlentities} | ||
116 | + {/switch} | ||
117 | + </div> | ||
118 | + <div class="col-sm-4"></div> | ||
119 | + </div> | ||
120 | + | ||
121 | + </td> | ||
122 | + </tr> | ||
123 | + {/foreach} | ||
124 | + </tbody> | ||
125 | + </table> | ||
126 | + <div class="form-group layer-footer"> | ||
127 | + <label class="control-label col-xs-12 col-sm-2"></label> | ||
128 | + <div class="col-xs-12 col-sm-8"> | ||
129 | + <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button> | ||
130 | + <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> | ||
131 | + </div> | ||
132 | + </div> | ||
133 | +</form> | ||
134 | + | ||
135 | + | ||
136 | + | ||
137 | +<script> | ||
138 | + require.callback = function () { | ||
139 | + var tabevent = function () { | ||
140 | + $(document).on("click", ".nav-group li a[data-toggle='tab']", function () { | ||
141 | + var type = $(this).attr("href").substring(1); | ||
142 | + if (type == 'all') { | ||
143 | + $(".table-config tr").show(); | ||
144 | + } else { | ||
145 | + $(".table-config tr").hide(); | ||
146 | + $(".table-config tr[data-type='" + type + "']").show(); | ||
147 | + } | ||
148 | + }); | ||
149 | + }; | ||
150 | + define('backend/addon', ['jquery', 'form'], function ($, Form) { | ||
151 | + var Controller = { | ||
152 | + config: function () { | ||
153 | + Form.api.bindevent($("form[role=form]")); | ||
154 | + tabevent(); | ||
155 | + } | ||
156 | + }; | ||
157 | + return Controller; | ||
158 | + }); | ||
159 | + define('backend/facrm/apps/config', ['jquery', 'form'], function ($, Form) { | ||
160 | + var Controller = { | ||
161 | + index: function () { | ||
162 | + Form.api.bindevent($("form[role=form]")); | ||
163 | + tabevent(); | ||
164 | + } | ||
165 | + }; | ||
166 | + return Controller; | ||
167 | + }); | ||
168 | + } | ||
169 | +</script> |
addons/facrm/config.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +return [ | ||
4 | + [ | ||
5 | + 'type' => 'array', | ||
6 | + 'name' => 'level', | ||
7 | + 'title' => '客户级别', | ||
8 | + 'value' => [ | ||
9 | + 1 => '重点客户', | ||
10 | + '优质客户', | ||
11 | + '普通客户', | ||
12 | + '0' =>'无级别', | ||
13 | + '10000' =>'其它', | ||
14 | + ], | ||
15 | + 'content' => [ | ||
16 | + 'value1' => 'title1', | ||
17 | + 'value2' => 'title2', | ||
18 | + ], | ||
19 | + 'tip' => '', | ||
20 | + 'rule' => '', | ||
21 | + 'extend' => '', | ||
22 | + ], | ||
23 | + [ | ||
24 | + 'type' => 'array', | ||
25 | + 'name' => 'industry', | ||
26 | + 'title' => '行业', | ||
27 | + 'value' => [ | ||
28 | + 1 => '金融业', | ||
29 | + '房地产', | ||
30 | + '商业服务', | ||
31 | + '贸易', | ||
32 | + '运输物流', | ||
33 | + '服务业', | ||
34 | + '文化传媒', | ||
35 | + 'IT/互联网', | ||
36 | + '其它', | ||
37 | + ], | ||
38 | + 'content' => [ | ||
39 | + 'value1' => 'title1', | ||
40 | + 'value2' => 'title2', | ||
41 | + ], | ||
42 | + 'tip' => '', | ||
43 | + 'rule' => '', | ||
44 | + 'extend' => '', | ||
45 | + ], | ||
46 | + [ | ||
47 | + 'type' => 'array', | ||
48 | + 'name' => 'source', | ||
49 | + 'title' => '客户来源', | ||
50 | + 'value' => [ | ||
51 | + 1 => '个人资源', | ||
52 | + '广告', | ||
53 | + '转介绍', | ||
54 | + '搜索引擎', | ||
55 | + '公司资源', | ||
56 | + '电话咨询', | ||
57 | + '官网咨询', | ||
58 | + '公众号', | ||
59 | + '抖音', | ||
60 | + '企业微信', | ||
61 | + 100000 => '其它', | ||
62 | + 0 => '无来源', | ||
63 | + ], | ||
64 | + 'content' => [ | ||
65 | + 'value1' => 'title1', | ||
66 | + 'value2' => 'title2', | ||
67 | + ], | ||
68 | + 'tip' => '', | ||
69 | + 'rule' => '', | ||
70 | + 'extend' => '', | ||
71 | + ], | ||
72 | + [ | ||
73 | + 'type' => 'array', | ||
74 | + 'name' => 'record_type', | ||
75 | + 'title' => '跟进方式', | ||
76 | + 'value' => [ | ||
77 | + 1 => '电话', | ||
78 | + '上门拜访', | ||
79 | + '微信', | ||
80 | + '短息', | ||
81 | + ], | ||
82 | + 'content' => [ | ||
83 | + 'value1' => 'title1', | ||
84 | + 'value2' => 'title2', | ||
85 | + ], | ||
86 | + 'tip' => '', | ||
87 | + 'rule' => '', | ||
88 | + 'extend' => '', | ||
89 | + ], | ||
90 | + [ | ||
91 | + 'type' => 'array', | ||
92 | + 'name' => 'account', | ||
93 | + 'title' => '收款账户', | ||
94 | + 'value' => [ | ||
95 | + 1 => '现金', | ||
96 | + '对公账户', | ||
97 | + '支付宝', | ||
98 | + '微信', | ||
99 | + '其它', | ||
100 | + ], | ||
101 | + 'content' => [ | ||
102 | + 'value1' => 'title1', | ||
103 | + 'value2' => 'title2', | ||
104 | + ], | ||
105 | + 'tip' => '', | ||
106 | + 'rule' => '', | ||
107 | + 'extend' => '', | ||
108 | + ], | ||
109 | + [ | ||
110 | + 'type' => 'number', | ||
111 | + 'name' => 'possess_num', | ||
112 | + 'title' => '可拥有客户', | ||
113 | + 'value' => '-1', | ||
114 | + 'content' => '', | ||
115 | + 'tip' => '限制一个员工能拥有的非成交客户数量。-1不限制', | ||
116 | + 'rule' => '', | ||
117 | + 'extend' => '', | ||
118 | + ], | ||
119 | + [ | ||
120 | + 'type' => 'number', | ||
121 | + 'name' => 'lose_day1', | ||
122 | + 'title' => '不跟进自动公海天数', | ||
123 | + 'value' => '-1', | ||
124 | + 'content' => '', | ||
125 | + 'tip' => '多少天不跟进自动成为公海-1关闭', | ||
126 | + 'rule' => '', | ||
127 | + 'extend' => '', | ||
128 | + ], | ||
129 | + [ | ||
130 | + 'type' => 'number', | ||
131 | + 'name' => 'lose_day2', | ||
132 | + 'title' => '不成交自动公海天数', | ||
133 | + 'value' => '-1', | ||
134 | + 'content' => '', | ||
135 | + 'tip' => '和跟进天数是或者关系-1关闭', | ||
136 | + 'rule' => '', | ||
137 | + 'extend' => '', | ||
138 | + ], | ||
139 | + [ | ||
140 | + 'type' => 'select', | ||
141 | + 'name' => 'unique', | ||
142 | + 'title' => '客户唯一字段', | ||
143 | + 'value' => 'name', | ||
144 | + 'content' => [ | ||
145 | + 'name' => '客户名称', | ||
146 | + 'mobile' => '手机', | ||
147 | + ], | ||
148 | + 'tip' => '校验客户唯一的字段', | ||
149 | + 'rule' => '', | ||
150 | + 'extend' => '', | ||
151 | + ], | ||
152 | + [ | ||
153 | + 'type' => 'radio', | ||
154 | + 'name' => 'show_contacts', | ||
155 | + 'title' => '显示联系', | ||
156 | + 'value' => '1', | ||
157 | + 'content' => [ | ||
158 | + 1 => '显示', | ||
159 | + '隐藏', | ||
160 | + ], | ||
161 | + 'tip' => '是否在客户列表显示手机和电话', | ||
162 | + 'rule' => '', | ||
163 | + 'extend' => '', | ||
164 | + ], | ||
165 | + [ | ||
166 | + 'type' => 'string', | ||
167 | + 'name' => 'min_app_id', | ||
168 | + 'title' => '小程序AppID', | ||
169 | + 'value' => '', | ||
170 | + 'content' => '', | ||
171 | + 'tip' => '', | ||
172 | + 'rule' => '', | ||
173 | + 'extend' => '', | ||
174 | + ], | ||
175 | + [ | ||
176 | + 'type' => 'string', | ||
177 | + 'name' => 'min_app_secret', | ||
178 | + 'title' => '小程序Secret', | ||
179 | + 'value' => '', | ||
180 | + 'content' => '', | ||
181 | + 'tip' => '', | ||
182 | + 'rule' => '', | ||
183 | + 'extend' => '', | ||
184 | + ], | ||
185 | + [ | ||
186 | + 'type' => 'string', | ||
187 | + 'name' => 'map_qq_key', | ||
188 | + 'title' => '腾讯地图KEY', | ||
189 | + 'value' => '', | ||
190 | + 'content' => '', | ||
191 | + 'tip' => '', | ||
192 | + 'rule' => '', | ||
193 | + 'extend' => '', | ||
194 | + ], | ||
195 | + [ | ||
196 | + 'type' => 'string', | ||
197 | + 'name' => 'cprefix', | ||
198 | + 'title' => '合同前缀', | ||
199 | + 'value' => '{:Y}{:m}{:d}{:h}{:i}{:s}{:rand}', | ||
200 | + 'content' => '', | ||
201 | + 'tip' => '{:Y}年,{:m}月,{:d}日,{:h}时,{:i}分{:s}秒,{:rand}6位随机数', | ||
202 | + 'rule' => '', | ||
203 | + 'extend' => '', | ||
204 | + ], | ||
205 | + [ | ||
206 | + 'type' => 'string', | ||
207 | + 'name' => 'rprefix', | ||
208 | + 'title' => '回款前缀', | ||
209 | + 'value' => '{:Y}{:m}{:d}{:h}{:i}{:s}{:rand}', | ||
210 | + 'content' => '', | ||
211 | + 'tip' => '{:Y}年,{:m}月,{:d}日,{:h}时,{:i}分{:s}秒,{:rand}6位随机数', | ||
212 | + 'rule' => '', | ||
213 | + 'extend' => '', | ||
214 | + ], | ||
215 | + [ | ||
216 | + 'type' => 'radio', | ||
217 | + 'name' => 'deal', | ||
218 | + 'title' => '手动成交', | ||
219 | + 'value' => '0', | ||
220 | + 'content' => [ | ||
221 | + 1 => '开启', | ||
222 | + 0 => '关闭', | ||
223 | + ], | ||
224 | + 'tip' => '开启可在跟进成交客户,不需要经过合同流程', | ||
225 | + 'rule' => '', | ||
226 | + 'extend' => '', | ||
227 | + ], | ||
228 | +]; |
addons/facrm/config/cache.php
0 → 100644
1 | +<?php | ||
2 | + return array ( | ||
3 | + 'table_name' => 'fa_facrm_achievement,fa_facrm_business,fa_facrm_business_contacts,fa_facrm_business_product,fa_facrm_cloudcall,fa_facrm_cloudcall_log,fa_facrm_clues,fa_facrm_contract,fa_facrm_contract_order,fa_facrm_contract_plan,fa_facrm_contract_product,fa_facrm_contract_receivables,fa_facrm_customer,fa_facrm_customer_contacts,fa_facrm_fields,fa_facrm_flow,fa_facrm_flow_log,fa_facrm_flow_step,fa_facrm_invoice,fa_facrm_notices,fa_facrm_operatelog,fa_facrm_product,fa_facrm_product_type,fa_facrm_product_unit,fa_facrm_qywx_contacts,fa_facrm_qywx_user,fa_facrm_record,fa_facrm_record_files,fa_facrm_scene,fa_facrm_setting,fa_facrm_tag', | ||
4 | + 'self_path' => 'public/assets/addons/facrm | ||
5 | +application/admin/lang/zh-cn/facrm', | ||
6 | + 'update_data' => '-- | ||
7 | +-- 1.0.1 | ||
8 | +-- 添加名称字段user_id | ||
9 | +-- | ||
10 | +ALTER TABLE `__PREFIX__facrm_customer` ADD COLUMN `user_id` int(11) NULL DEFAULT \'\' COMMENT \'前台用户ID\' AFTER `owner_user_id`; | ||
11 | + | ||
12 | + | ||
13 | +-- | ||
14 | +-- 1.0.3 | ||
15 | +-- 更改表编码和字段编码和增加字段 | ||
16 | +-- | ||
17 | +ALTER TABLE `__PREFIX__facrm_customer` DEFAULT CHARACTER SET utf8mb4, | ||
18 | +MODIFY COLUMN `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT \'客户名称\' , | ||
19 | +MODIFY COLUMN `remark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT \'备注\' ; | ||
20 | + | ||
21 | +ALTER TABLE `__PREFIX__facrm_customer_contacts` DEFAULT CHARACTER SET utf8mb4, | ||
22 | +MODIFY COLUMN `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT \'姓名\' , | ||
23 | +MODIFY COLUMN `remark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT \'备注\' ; | ||
24 | + | ||
25 | +ALTER TABLE `__PREFIX__facrm_record` DEFAULT CHARACTER SET utf8mb4, | ||
26 | +MODIFY COLUMN `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT \'跟进内容\' ; | ||
27 | + | ||
28 | +ALTER TABLE `__PREFIX__facrm_setting` ADD COLUMN `status` tinyint(1) NULL DEFAULT \'1\' COMMENT \'状态\' AFTER `create_time`; | ||
29 | + | ||
30 | +-- | ||
31 | +-- 2.0.0 | ||
32 | +-- 更改表编码和字段编码和增加字段 | ||
33 | +-- | ||
34 | +ALTER TABLE `__PREFIX__facrm_record` | ||
35 | +MODIFY COLUMN `types` enum(\'business\',\'clues\',\'customer\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT \'customer\' COMMENT \'关联类型(customer跟进,business商机跟进,clues线索)\' AFTER `id`; | ||
36 | + | ||
37 | + | ||
38 | +ALTER TABLE `__PREFIX__facrm_record_files` | ||
39 | +MODIFY COLUMN `types` enum(\'business\',\'clues\',\'customer\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT \'customer\' COMMENT \'关联类型(customer客户,business商机,clues线索)\' AFTER `id`; | ||
40 | + | ||
41 | + | ||
42 | +-- | ||
43 | +-- 插入一些必须数据 | ||
44 | +-- | ||
45 | +INSERT INTO __PREFIX__facrm_flow VALUES (\'1\', \'合同审批\', \'0\', \'contract\', \'0\', \'\', \'\', \'\', \'1610787200\', \'1610787643\', \'1\', null,1); | ||
46 | +INSERT INTO __PREFIX__facrm_flow VALUES (\'2\', \'回款审批\', \'0\', \'receivables\', \'0\', \'\', \'\', \'\', \'1610947811\', \'1618023534\', \'1\', null,2); | ||
47 | +INSERT INTO __PREFIX__facrm_flow VALUES (\'3\', \'发票申请\', \'0\', \'invoice\', \'0\', \'\', \'\', \'\', \'1610947811\', \'1618023534\', \'1\', null,3); | ||
48 | +INSERT INTO __PREFIX__facrm_fields VALUES (\'1\', \'customer\', \'weixin\', \'string\', \'微信\', \'value1|title1\\r\\nvalue2|title2\', \'\', \'\', \'\', \'\', \'\', \'0\', \'50\', \'0\', \'0\', \'\', \'{\\"table\\":\\"\\",\\"conditions\\":\\"\\",\\"key\\":\\"\\",\\"value\\":\\"\\"}\', \'22\', \'1614587422\', \'1614664611\', \'0\', \'0\', \'1\', \'1\', \'normal\'); | ||
49 | +INSERT INTO __PREFIX__facrm_fields VALUES (\'2\', \'customer\', \'qq\', \'number\', \'QQ\', \'value1|title1\\r\\nvalue2|title2\', \'\', \'\', \'\', \'\', \'\', \'0\', \'11\', \'0\', \'0\', \'\', \'{\\"table\\":\\"\\",\\"conditions\\":\\"\\",\\"key\\":\\"\\",\\"value\\":\\"\\"}\', \'25\', \'1614587924\', \'1614667071\', \'0\', \'1\', \'0\', \'1\', \'normal\'); | ||
50 | + | ||
51 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'1\', \'customer\', \'全部客户\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
52 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'2\', \'customer\', \'我的客户\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
53 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'3\', \'customer\', \'下属客户\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
54 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'4\', \'contacts\', \'全部\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
55 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'5\', \'contacts\', \'我的\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
56 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'6\', \'contacts\', \'下属\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
57 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'7\', \'business\', \'全部商机\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
58 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'8\', \'business\', \'我的商机\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
59 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'9\', \'business\', \'下属商机\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
60 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'10\', \'clues\', \'全部线索\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
61 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'11\', \'clues\', \'我的线索\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
62 | +INSERT INTO __PREFIX__facrm_scene VALUES (\'12\', \'clues\', \'下属线索\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\'); | ||
63 | + | ||
64 | +-- | ||
65 | +-- 2.0.2 | ||
66 | +-- 添加来源字段 | ||
67 | +-- | ||
68 | +ALTER TABLE `__PREFIX__facrm_contract` | ||
69 | +ADD COLUMN `source_id` int(11) NULL DEFAULT 0 COMMENT \'来源ID\' AFTER `contacts_id`; | ||
70 | + | ||
71 | +-- | ||
72 | +-- 2.0.5 | ||
73 | +-- 增加云呼方式 | ||
74 | +-- | ||
75 | +ALTER TABLE `__PREFIX__facrm_cloudcall` | ||
76 | +MODIFY COLUMN `exten_type` enum(\'gateway\',\'sip\',\'local\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT \'local\' COMMENT \'接听方式Local为“手机”\' AFTER `from_exten`; | ||
77 | + | ||
78 | +-- | ||
79 | +-- 2.0.6 | ||
80 | +-- 增加线上收款 | ||
81 | +-- | ||
82 | +ALTER TABLE `__PREFIX__facrm_record` | ||
83 | +ADD COLUMN `lng` double(14,11) NULL COMMENT \'经度\' AFTER `delete_time`, | ||
84 | +ADD COLUMN `lat` double(14,11) NULL COMMENT \'维度\' AFTER `lng`; | ||
85 | + | ||
86 | +ALTER TABLE `__PREFIX__facrm_contract_receivables` | ||
87 | +ADD COLUMN `pay_status` tinyint(4) NULL DEFAULT 0 COMMENT \'在线支付状态1已付款0未付款\' AFTER `delete_time`, | ||
88 | +ADD COLUMN `pay_type` tinyint(4) NULL DEFAULT 1 COMMENT \'收款方式1默认2在线收款3续费\' AFTER `pay_status`, | ||
89 | +ADD COLUMN `pay_token` varchar(200) NULL COMMENT \'访问支付的token\' AFTER `pay_type`; | ||
90 | + | ||
91 | + | ||
92 | + | ||
93 | +-- | ||
94 | +-- 2.0.7 | ||
95 | +-- 发票 | ||
96 | +-- | ||
97 | +ALTER TABLE `__PREFIX__facrm_flow` | ||
98 | +ADD COLUMN `weigh` int(11) NULL DEFAULT 0 COMMENT \'权重\' AFTER `delete_time`, | ||
99 | +MODIFY COLUMN `types` enum(\'contract\',\'invoice\',\'receivables\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT \'关联对象\' AFTER `config`; | ||
100 | + | ||
101 | +ALTER TABLE `__PREFIX__facrm_flow_log` | ||
102 | +MODIFY COLUMN `types` enum(\'contract\',\'invoice\',\'receivables\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT \'关联对象\' AFTER `flow_id`; | ||
103 | + | ||
104 | +ALTER TABLE `__PREFIX__facrm_contract` | ||
105 | +ADD COLUMN `invoice_money` decimal(10,2) NULL DEFAULT 0.00 COMMENT \'已开票金额\' ; | ||
106 | + | ||
107 | +-- | ||
108 | +-- 2.0.8 | ||
109 | +-- 消费总额和次数 | ||
110 | +-- | ||
111 | +ALTER TABLE `__PREFIX__facrm_customer` | ||
112 | +ADD COLUMN `purchase_total` decimal(18,2) NULL DEFAULT 0 COMMENT \'消费总额\' AFTER `qq`, | ||
113 | +ADD COLUMN `purchase_times` int(10) NULL DEFAULT 0 COMMENT \'消费次数\' AFTER `purchase_total`; | ||
114 | + | ||
115 | +-- 2.0.10 | ||
116 | +INSERT INTO `__PREFIX__facrm_scene` (`id`, `types`, `name`, `admin_id`, `create_time`, `update_time`) VALUES (13,\'customer\', \'分享给他人\', \'0\', \'0\', \'0\'); | ||
117 | +INSERT INTO `__PREFIX__facrm_scene` (`id`,`types`, `name`, `admin_id`, `create_time`, `update_time`) VALUES (14,\'customer\', \'分享给我的\', \'0\', \'0\', \'0\'); | ||
118 | + | ||
119 | +--2.1.0 | ||
120 | +-- 增加自定义跟进状态 | ||
121 | +ALTER TABLE `__PREFIX__facrm_customer` | ||
122 | +ADD COLUMN `follow_status` enum(\'1\',\'2\',\'3\',\'4\',\'5\',\'0\') DEFAULT \'1\' COMMENT \'跟进状态\'; | ||
123 | +ALTER TABLE `__PREFIX__facrm_clues` | ||
124 | +ADD COLUMN `follow_status` enum(\'1\',\'2\',\'3\',\'4\',\'5\',\'0\') DEFAULT \'1\' COMMENT \'跟进状态\'; | ||
125 | + | ||
126 | +--2.2.5 | ||
127 | +-- 增加回款计划 | ||
128 | +ALTER TABLE `__PREFIX__facrm_contract_receivables` | ||
129 | +ADD COLUMN `plan_id` int(11) NOT NULL DEFAULT 0 COMMENT \'关联回款计划\' AFTER `pay_token`; | ||
130 | + | ||
131 | +INSERT INTO `__PREFIX__facrm_fields` ( `id`,`source`,`name`,`type`,`title`,`content`,`defaultvalue`,`rule` ,`msg`,`ok`,`tip`,`decimals`,`length`,`minimum`,`maximum`,`extend`,`setting`,`weigh`,`createtime`,`updatetime`,`isorder`,`iscontribute`,`islist`,`isfilter`,`status`) VALUES (3, \'customer\', \'follow_status\', \'select\', \'跟进状态\', \'1|新客\\r\\n2|待再次沟通\\r\\n3|有意向\\r\\n4|已加微信\\r\\n5|转商机\\r\\n0|无效\', \'1\', \'\', \'\', \'\', \'\', \'0\', \'4\', \'0\', \'0\', \'\', \'{\\"table\\":\\"\\",\\"conditions\\":\\"\\",\\"key\\":\\"\\",\\"value\\":\\"\\"}\', \'6\', \'1694851354\', \'1694851354\', \'0\', \'0\', \'0\', \'0\', \'normal\'); | ||
132 | + | ||
133 | +INSERT INTO `__PREFIX__facrm_fields` ( `id`,`source`,`name`,`type`,`title`,`content`,`defaultvalue`,`rule` ,`msg`,`ok`,`tip`,`decimals`,`length`,`minimum`,`maximum`,`extend`,`setting`,`weigh`,`createtime`,`updatetime`,`isorder`,`iscontribute`,`islist`,`isfilter`,`status`) VALUES (4, \'clues\', \'follow_status\', \'select\', \'跟进状态\', \'1|新客\\r\\n2|待再次沟通\\r\\n3|有意向\\r\\n4|已加微信\\r\\n5|转商机\\r\\n0|无效\', \'1\', \'\', \'\', \'\', \'\', \'0\', \'4\', \'0\', \'0\', \'\', \'{\\"table\\":\\"\\",\\"conditions\\":\\"\\",\\"key\\":\\"\\",\\"value\\":\\"\\"}\', \'6\', \'1694851354\', \'1694851354\', \'0\', \'0\', \'0\', \'0\', \'normal\'); | ||
134 | +', | ||
135 | +); |
addons/facrm/config/cluesfield.php
0 → 100644
1 | +<?php | ||
2 | +/** | ||
3 | + * 自定义表排序 | ||
4 | + */ | ||
5 | + | ||
6 | +return array( | ||
7 | + | ||
8 | + array("field" => 'id', "title" => '线索ID', "sortable" => true), | ||
9 | + | ||
10 | + array("field" => 'name', "title" => '线索名称', "operate" => "LIKE", "align" => 'left', 'customField' => 'tags', "class" => "tabletd", | ||
11 | + "formatter" => '(function (value, row, index) { | ||
12 | + value=\'<a href="javascript:void(0);" data-url="facrm/clues/index/edit/ids/\' + row.id | ||
13 | + +\'" data-area="["98%","98%"]" class="btn-dialog" data-title="\'+ row.name+\'">\'+ row.name+\'</a>\'; | ||
14 | + return value + | ||
15 | + \'<div >\' + Table.api.formatter.flag.call(this, row[\'tags\'], row, index) + \'</div>\'; | ||
16 | + })', | ||
17 | + "cellStyle" => '(function(value, row, index, field){return {css: {"max-width":"200px"}};})'), | ||
18 | + | ||
19 | + array("field" => 'tags', "title" => '标签', "visible" => false, "formatter" => "Table.api.formatter.flag", "operate" => 'find_in_set'), | ||
20 | + array("field" => 'level', "title" => '级别', "formatter" => "Table.api.formatter.status", "searchList" => 'levelList'), | ||
21 | + array("field" => 'industry', "title" => '行业', "formatter" => "(function (v, row, index) { | ||
22 | + if(!v) return '无'; | ||
23 | + return industryList[v]; | ||
24 | + })", "searchList" => 'industryList'), | ||
25 | + | ||
26 | + array("field" => 'source', "title" => '来源', "formatter" => "(function (v, row, index) { | ||
27 | + if(!v) return '无'; | ||
28 | + return sourceList[v]; | ||
29 | + })", "searchList" => 'sourceList'), | ||
30 | + array("field" => 'telephone', "title" => '电话', "operate" => "LIKE"), | ||
31 | + array("field" => 'mobile', "title" => '手机', "operate" => "LIKE"), | ||
32 | + | ||
33 | + array("field" => 'remark', "title" => '备注', "operate" => "LIKE", "class" => "tabletd", "align" => "left", "cellStyle" => "(function(value, row, index, field){ | ||
34 | + return {css: { \"max-width\":\"250px\"}}; | ||
35 | + })"), | ||
36 | + array("field" => 'status', "title" => '状态', "formatter" => "Table.api.formatter.status", "searchList" => 'status_obj'), | ||
37 | + | ||
38 | + array("field" => 'owner_user_id', "title" => '负责人', "addclass" => "selectpage", "class" => "tabletd", "cellStyle" => "(function(value, row, index, field){ | ||
39 | + return {css: { \"max-width\":\"200px\"}}; | ||
40 | + })", | ||
41 | + 'formatter' => "(function (v, r) { | ||
42 | + if (!r.owner_user) return '-'; | ||
43 | + return r.owner_user.nickname;})", | ||
44 | + 'extend' => 'data-source="facrm/common/selectpage/model/admin?type=children" data-field="nickname" data-orderBy="id desc"' | ||
45 | + ), | ||
46 | + array("field" => 'create_user_id', "title" => '创建人', "addclass" => "selectpage", "formatter" => '(function (v, r) { | ||
47 | + if (!r.create_user) return \'-\'; | ||
48 | + return r.create_user.nickname; | ||
49 | + })', | ||
50 | + "extend" => 'data-source="facrm/common/selectpage/model/admin?type=children" data-field="nickname" data-orderBy="id desc"', | ||
51 | + ), | ||
52 | + array("field" => 'next_time', "title" => '下次跟进', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
53 | + array("field" => 'follow_time', "title" => '最近跟进', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
54 | + array("field" => 'create_time', "title" => '创建时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
55 | + array("field" => 'collect_time', "title" => '领取时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
56 | + array("field" => 'update_time', "title" => '更新时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
57 | + | ||
58 | + | ||
59 | + | ||
60 | +); |
addons/facrm/config/contractfield.php
0 → 100644
1 | +<?php | ||
2 | +/** | ||
3 | + * 合同自定义表排序 | ||
4 | + */ | ||
5 | + | ||
6 | +return array( | ||
7 | + array("field" => 'id', "title" => '合同ID', "sortable" => true), | ||
8 | + array("field" => 'number', "title" => '合同编号', "operate" => "LIKE", "align" => 'left', | ||
9 | + "formatter" => '(function (value, row, index) { | ||
10 | + return \'<a href="javascript:void(0);" data-url="facrm/contract/index/detail/ids/\' + row.id | ||
11 | + + \'" data-area="["98%","98%"]" class="btn-dialog" data-title="\' + value + \'">\' + value + \'</a>\'; | ||
12 | + })',), | ||
13 | + array("field" => 'name', "title" => '合同名称', "operate" => "LIKE", "align" => 'left', | ||
14 | + "formatter" => '(function (value, row, index) { | ||
15 | + //判断是否逾期 | ||
16 | + var newtime = Math.round(new Date().getTime() / 1000).toString(); | ||
17 | + if (newtime > row.end_time) | ||
18 | + value = \'<span class="label label-danger">过期</span>\' + value; | ||
19 | + return value; | ||
20 | + })',), | ||
21 | + array("field" => 'customer_id', "title" => '客户名称', "align" => 'left', | ||
22 | + "formatter" => '(function (value, row, index) { | ||
23 | + if (!row.customer) return \'-\'; | ||
24 | + return \'<a href="javascript:void(0);" data-url="facrm/customer/index/detail/ids/\' + row.customer.id | ||
25 | + + \'" data-area="["98%","98%"]" class="btn-dialog" data-title="\' + row.customer.name + \'">\' + row.customer.name + \'(\' + row.customer_id + \')\' + \'</a>\'; | ||
26 | + })', | ||
27 | + "addclass" => "selectpage", 'extend' => 'data-source="facrm/customer/index?filter=%7B\"scene_id\"%3A\"1\"%7D" data-field="name" data-orderBy="id desc"'), | ||
28 | + | ||
29 | + array("field" => 'money', "title" => '合同金额', "sortable" => true, 'operate' => 'BETWEEN'), | ||
30 | + array("field" => 'return_money', "title" => '回款金额', "sortable" => true, 'operate' => 'BETWEEN'), | ||
31 | + array("field" => 'order_time', "title" => '下单时间', "sortable" => true, 'operate' => 'RANGE', "formatter" => "Table.api.formatter.datetime", | ||
32 | + 'datetimeFormat'=>"YYYY/MM/DD","extend"=>'autocomplete="off" data-time-picker="true"','addclass'=>'datetimerange'), | ||
33 | + array("field" => 'remark', "title" => '备注', "align" => "left", 'operate' => 'LIKE'), | ||
34 | + array("field" => 'start_time', "title" => '开始时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
35 | + array("field" => 'end_time', "title" => '结束时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
36 | + array("field" => 'product', "title" => '订购商品', "operate" => false, "align" => 'left', | ||
37 | + "formatter" => '(function (value, row, index) { | ||
38 | + if (!value||value.length == 0) { | ||
39 | + return "商品有误"; | ||
40 | + } | ||
41 | + text = ""; | ||
42 | + for (i = 0; i < value.length; i++) { | ||
43 | + text += "编码:" + value[i].sku + "|数量:" + value[i].nums +"|" + value[i].name + "" + " <br>"; | ||
44 | + } | ||
45 | + return Table.api.formatter.content(text, row, index); | ||
46 | + })',), | ||
47 | + | ||
48 | + | ||
49 | + array("field" => 'create_user_id', "title" => '创建人', "addclass" => "selectpage", "formatter" => '(function (v, r) { | ||
50 | + if (!r.create_user) return \'-\'; | ||
51 | + return r.create_user.nickname; | ||
52 | + })', | ||
53 | + "extend" => 'data-source="facrm/common/selectpage/model/admin?type=all" data-field="nickname" data-orderBy="id desc"', | ||
54 | + ), | ||
55 | + | ||
56 | + array("field" => 'order_admin_id', "title" => '签约人', "addclass" => "selectpage", "formatter" => '(function (v, r) { | ||
57 | + if (!r.order_admin) return \'-\'; | ||
58 | + return r.order_admin.nickname; | ||
59 | + })', | ||
60 | + "extend" => 'data-source="facrm/common/selectpage/model/admin?type=all" data-field="nickname" data-orderBy="id desc"', | ||
61 | + ), | ||
62 | + | ||
63 | + array("field" => 'create_time', "title" => '创建时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
64 | + array("field" => 'check_status', "title" => '状态', "formatter" => "Table.api.formatter.status", "searchList" => 'check_status'), | ||
65 | + | ||
66 | + | ||
67 | + | ||
68 | +); |
addons/facrm/config/customerfield.php
0 → 100644
1 | +<?php | ||
2 | +/** | ||
3 | + * 客户自定义表排序 | ||
4 | + */ | ||
5 | + | ||
6 | +return array( | ||
7 | + | ||
8 | + array("field" => 'id', "title" => '客户ID', "sortable" => true), | ||
9 | + | ||
10 | + array("field" => 'name', "title" => '客户名称', "operate" => "LIKE", "align" => 'left', 'customField' => 'tags', "class" => "tabletd", | ||
11 | + "formatter" => '(function (value, row, index) { | ||
12 | + value=\'<a href="javascript:void(0);" data-url="facrm/customer/record/add/ids/\' + row.id | ||
13 | + +\'" data-area="["98%","98%"]" class="btn-addtabs" data-toggle="tooltip" data-original-title="\'+ value+\'" data-title="\'+ value+\'">\'+ value+\'</a>\'; | ||
14 | + | ||
15 | + | ||
16 | + return value + | ||
17 | + \'<div >\' + Table.api.formatter.flag.call(this, row[\'tags\'], row, index) + \'</div>\'; | ||
18 | + })', | ||
19 | + | ||
20 | + "cellStyle" => '(function(value, row, index, field){return {css: {"max-width":"200px"}};})'), | ||
21 | + | ||
22 | + array("field" => 'tags', "title" => '标签', "visible" => false, "formatter" => "Table.api.formatter.flag", "operate" => 'find_in_set'), | ||
23 | + array("field" => 'telephone', "title" => '电话', "operate" => "LIKE"), | ||
24 | + array("field" => 'mobile', "title" => '手机', "operate" => "LIKE"), | ||
25 | + | ||
26 | + array("field" => 'owner_user_id', "title" => '负责人', "addclass" => "selectpage", "class" => "tabletd", "cellStyle" => "(function(value, row, index, field){ | ||
27 | + return {css: { \"max-width\":\"200px\"}}; | ||
28 | + })", | ||
29 | + 'formatter' => "(function (v, r) { | ||
30 | + if (!r.owner_user) return '-'; | ||
31 | + return r.owner_user.nickname;})", | ||
32 | + 'extend' => 'data-source="facrm/common/selectpage/model/admin?type=children" data-field="nickname" data-orderBy="id desc"' | ||
33 | + ), | ||
34 | + array("field" => 'deal_status', "title" => '成交状态', "formatter" => "Table.api.formatter.status", "searchList" => 'deal_status'), | ||
35 | + array("field" => 'remark', "title" => '备注', "operate" => "LIKE", "class" => "tabletd", "align" => "left", "cellStyle" => "(function(value, row, index, field){ | ||
36 | + return {css: { \"max-width\":\"250px\"}}; | ||
37 | + })"), | ||
38 | + array("field" => 'level', "title" => '客户级别', "formatter" => "Table.api.formatter.status", "searchList" => 'levelList'), | ||
39 | + array("field" => 'industry', "title" => '行业', "formatter" => "(function (v, row, index) { | ||
40 | + if(!v) return '无'; | ||
41 | + return industryList[v]; | ||
42 | + })", "searchList" => 'industryList'), | ||
43 | + | ||
44 | + array("field" => 'source', "title" => '来源', "formatter" => "Table.api.formatter.status", "searchList" => 'sourceList'), | ||
45 | + array("field" => 'create_user_id', "title" => '创建人', "addclass" => "selectpage", "formatter" => '(function (v, r) { | ||
46 | + if (!r.create_user) return \'-\'; | ||
47 | + return r.create_user.nickname; | ||
48 | + })', | ||
49 | + "extend" => 'data-source="facrm/common/selectpage/model/admin?type=children" data-field="nickname" data-orderBy="id desc"', | ||
50 | + ), | ||
51 | + array("field" => 'next_time', "title" => '下次跟进', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
52 | + array("field" => 'follow_time', "title" => '最近跟进', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
53 | + array("field" => 'create_time', "title" => '创建时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
54 | + array("field" => 'collect_time', "title" => '领取时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
55 | + array("field" => 'update_time', "title" => '更新时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'), | ||
56 | + | ||
57 | + | ||
58 | + | ||
59 | +); |
addons/facrm/config/menu.php
0 → 100644
此 diff 太大无法显示。
addons/facrm/controller/Autotask.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller; | ||
4 | + | ||
5 | +use EasyWeChat\Factory; | ||
6 | +use think\Config; | ||
7 | +use think\Db; | ||
8 | +use think\Queue; | ||
9 | + | ||
10 | +/** | ||
11 | + * 定时任务 | ||
12 | + * @internal | ||
13 | + */ | ||
14 | +class Autotask extends \think\addons\Controller | ||
15 | +{ | ||
16 | + protected $noNeedLogin = ["*"]; | ||
17 | + protected $layout = ''; | ||
18 | + | ||
19 | + public function _initialize() | ||
20 | + { | ||
21 | + set_time_limit(0); | ||
22 | + parent::_initialize(); | ||
23 | + | ||
24 | + if (!$this->request->isCli()) { | ||
25 | + $this->error('只允许在终端进行操作!'); | ||
26 | + } | ||
27 | + } | ||
28 | + | ||
29 | + /** | ||
30 | + * 定时任务逻辑 | ||
31 | + */ | ||
32 | + public function index() | ||
33 | + { | ||
34 | + $this->flowcustomer(); | ||
35 | + $this->flowbusiness(); | ||
36 | + $this->expirecontract(); | ||
37 | + $this->expirecustomer(); | ||
38 | + $this->flowclues(); | ||
39 | + } | ||
40 | + | ||
41 | + /** | ||
42 | + * 待跟进客户提醒 | ||
43 | + */ | ||
44 | + public function flowcustomer() | ||
45 | + { | ||
46 | + | ||
47 | + //当天开始时间 | ||
48 | + $start_time = strtotime(date("Y-m-d", time())); | ||
49 | + //当天结束之间 | ||
50 | + $end_time = $start_time + 60 * 60 * 24; | ||
51 | + $customerModel = model('\app\admin\model\facrm\Customer'); | ||
52 | + //需要联系客户 | ||
53 | + $communicate = $customerModel->where('next_time', 'between', [1, $end_time]) | ||
54 | + ->field('COUNT(*) AS count,owner_user_id ') | ||
55 | + ->where('owner_user_id', "<>", '0') | ||
56 | + ->group('owner_user_id') | ||
57 | + ->select(); | ||
58 | + | ||
59 | + foreach ($communicate as $row) { | ||
60 | + if ($row->count <= 0) continue; | ||
61 | + //通知队列 | ||
62 | + Queue::push("addons\\facrm\\library\\notice\queue\\CustomerJob", [ | ||
63 | + 'key' => 'notice_flow_customer',//待跟进通知模板 | ||
64 | + 'admin_ids' => $row->owner_user_id, | ||
65 | + 'count' => $row->count, | ||
66 | + ]); | ||
67 | + } | ||
68 | + echo "done"; | ||
69 | + return; | ||
70 | + } | ||
71 | + | ||
72 | + /** | ||
73 | + * 待跟进线索提醒 | ||
74 | + */ | ||
75 | + public function flowclues() | ||
76 | + { | ||
77 | + | ||
78 | + //当天开始时间 | ||
79 | + $start_time = strtotime(date("Y-m-d", time())); | ||
80 | + //当天结束之间 | ||
81 | + $end_time = $start_time + 60 * 60 * 24; | ||
82 | + $cluesModel = model('\app\admin\model\facrm\Clues'); | ||
83 | + //需要联系线索 | ||
84 | + $communicate = $cluesModel->where('next_time', 'between', [1, $end_time]) | ||
85 | + ->field('COUNT(*) AS count,owner_user_id ') | ||
86 | + ->where('owner_user_id', "<>", '0') | ||
87 | + ->group('owner_user_id') | ||
88 | + ->select(); | ||
89 | + | ||
90 | + foreach ($communicate as $row) { | ||
91 | + if ($row->count <= 0) continue; | ||
92 | + //通知队列 | ||
93 | + Queue::push("addons\\facrm\\library\\notice\queue\\CluesJob", [ | ||
94 | + 'key' => 'notice_flow_clues',//待跟进通知模板 | ||
95 | + 'admin_ids' => $row->owner_user_id, | ||
96 | + 'count' => $row->count, | ||
97 | + ]); | ||
98 | + } | ||
99 | + echo "done"; | ||
100 | + return; | ||
101 | + } | ||
102 | + | ||
103 | + /** | ||
104 | + * 待跟进商机提醒 | ||
105 | + */ | ||
106 | + public function flowbusiness() | ||
107 | + { | ||
108 | + //当天开始时间 | ||
109 | + $start_time = strtotime(date("Y-m-d", time())); | ||
110 | + //当天结束之间 | ||
111 | + $end_time = $start_time + 60 * 60 * 24; | ||
112 | + $thisModel = model('\app\admin\model\facrm\Business'); | ||
113 | + //需要联系 | ||
114 | + $communicate = $thisModel->where('next_time', 'between', [1, $end_time]) | ||
115 | + ->where('is_end', 0) | ||
116 | + ->field('COUNT(*) AS count,owner_user_id ') | ||
117 | + ->where('owner_user_id', "<>", '0') | ||
118 | + ->group('owner_user_id') | ||
119 | + ->select(); | ||
120 | + | ||
121 | + foreach ($communicate as $row) { | ||
122 | + if ($row->count <= 0) continue; | ||
123 | + //通知队列 | ||
124 | + Queue::push("addons\\facrm\\library\\notice\queue\\BusinessrJob", [ | ||
125 | + 'key' => 'notice_flow_business',//待跟进通知模板 | ||
126 | + 'admin_ids' => $row->owner_user_id, | ||
127 | + 'count' => $row->count, | ||
128 | + ]); | ||
129 | + } | ||
130 | + echo "done"; | ||
131 | + return; | ||
132 | + } | ||
133 | + | ||
134 | + /** | ||
135 | + * 将过期合同(提前三十天) | ||
136 | + */ | ||
137 | + public function expirecontract() | ||
138 | + { | ||
139 | + | ||
140 | + //当天开始时间 | ||
141 | + $start_time = strtotime(date("Y-m-d", time())); | ||
142 | + //当天结束之间 | ||
143 | + $end_time = $start_time + 60 * 60 * 24; | ||
144 | + $thisModel = model('\app\admin\model\facrm\Contract'); | ||
145 | + //需要联系 | ||
146 | + $communicate = $thisModel->where('end_time', 'between', [1, $end_time + (30 * 86400)]) | ||
147 | + ->where('expire_handle', 0) | ||
148 | + ->field('COUNT(*) AS count,owner_user_id ') | ||
149 | + ->where('owner_user_id', "<>", '0') | ||
150 | + ->group('owner_user_id') | ||
151 | + ->select(); | ||
152 | + | ||
153 | + foreach ($communicate as $row) { | ||
154 | + if ($row->count <= 0) continue; | ||
155 | + //通知队列 | ||
156 | + Queue::push("addons\\facrm\\library\\notice\queue\\ContractJob", [ | ||
157 | + 'key' => 'notice_expire_contract',//待跟进通知模板 | ||
158 | + 'admin_ids' => $row->owner_user_id, | ||
159 | + 'count' => $row->count, | ||
160 | + ]); | ||
161 | + } | ||
162 | + echo "done"; | ||
163 | + return; | ||
164 | + | ||
165 | + } | ||
166 | + | ||
167 | + | ||
168 | + /** | ||
169 | + * 将要过期客户提醒 | ||
170 | + */ | ||
171 | + public function expirecustomer() | ||
172 | + { | ||
173 | + | ||
174 | + $config = get_addon_config('facrm'); | ||
175 | + //判断是否开启过期的功能 | ||
176 | + if ($config['lose_day1'] <= 0 && ($config['lose_day2'] <= 0)) { | ||
177 | + echo "done none"; | ||
178 | + return; | ||
179 | + } | ||
180 | + | ||
181 | + $thisModel = model('\app\admin\model\facrm\Customer'); | ||
182 | + | ||
183 | + $lists = $thisModel->getLoseWhere($config, 1) | ||
184 | + ->field('COUNT(*) AS count,owner_user_id ') | ||
185 | + ->where('owner_user_id', "<>", '0') | ||
186 | + ->group('owner_user_id') | ||
187 | + ->select(); | ||
188 | + | ||
189 | + foreach ($lists as $row) { | ||
190 | + if ($row->count <= 0) continue; | ||
191 | + //通知队列 | ||
192 | + Queue::push("addons\\facrm\\library\\notice\queue\\CustomerJob", [ | ||
193 | + 'key' => 'notice_expire_ccustomer',//客户将过期通知模板 | ||
194 | + 'admin_ids' => $row->owner_user_id, | ||
195 | + 'count' => $row->count, | ||
196 | + ]); | ||
197 | + } | ||
198 | + echo "done"; | ||
199 | + return; | ||
200 | + } | ||
201 | + | ||
202 | + | ||
203 | + /** | ||
204 | + * 云呼记录同步云呼建议1个小时执行一次【废弃已改用事件通知】 | ||
205 | + * @throws Exception | ||
206 | + * @throws \think\db\exception\DataNotFoundException | ||
207 | + * @throws \think\db\exception\ModelNotFoundException | ||
208 | + * @throws \think\exception\DbException | ||
209 | + */ | ||
210 | + public function calllog() | ||
211 | + { | ||
212 | + $this->key = "cloudcall"; | ||
213 | + //获取云呼配置 | ||
214 | + $all_types = \addons\facrm\library\cloudcall\Call::getProviders(); | ||
215 | + $keys = ""; | ||
216 | + foreach ($all_types as $v) { | ||
217 | + $keys .= $keys ? ',' . $this->key . $v : $this->key . $v; | ||
218 | + } | ||
219 | + $settingModel = new \app\admin\model\facrm\Setting(); | ||
220 | + $setting = $settingModel->where('key', 'in', $keys)->where('status', 1)->find();//只找一条云呼通道 | ||
221 | + | ||
222 | + if (!$setting) { | ||
223 | + $this->error(__("云呼通道没有配置,请先配置")); | ||
224 | + } | ||
225 | + //获取坐席 | ||
226 | + | ||
227 | + $setting = $setting->toArray(); | ||
228 | + $setting['key'] = $setting['describe']; | ||
229 | + $setting = array_merge($setting, $setting['values']); | ||
230 | + $call = \addons\facrm\library\cloudcall\Call::instance($setting); | ||
231 | + | ||
232 | + | ||
233 | + $calldata['beginTime'] = datetime(time() - (86400 * 1), 'Y-m-d H:i:s');//开始时间 | ||
234 | + $calldata['endTime'] = datetime(time(), 'Y-m-d H:i:s');//结束时间 | ||
235 | + | ||
236 | + | ||
237 | + $result = $call->getCallRecord($calldata); | ||
238 | + if (!$result) { | ||
239 | + $this->error($call->getError()); | ||
240 | + } | ||
241 | + $result = json_decode($result, true); | ||
242 | + if (isset($result['success']) && $result['success'] && $result['data']) { | ||
243 | + $cloudcallLog = new \app\admin\model\facrm\CloudcallLog(); | ||
244 | + foreach ($result['data'] as $r) { | ||
245 | + if (!$r['ACTION_ID']) continue; | ||
246 | + | ||
247 | + $log = $cloudcallLog->where('action_id', $r['ACTION_ID'])->where('status', 0)->find(); | ||
248 | + if (!$log) continue; | ||
249 | + | ||
250 | + $log->call_no = $r['CALL_NO']; | ||
251 | + $log->status = $r['STATUS'] == 'dealing' ? 1 : -1; | ||
252 | + $log->record_file = $r['FILE_SERVER'] . '/' . $r['RECORD_FILE_NAME']; | ||
253 | + $log->call_time_length = $r['CALL_TIME_LENGTH']; | ||
254 | + | ||
255 | + $log->save(); | ||
256 | + } | ||
257 | + | ||
258 | + } | ||
259 | + } | ||
260 | + | ||
261 | + /** | ||
262 | + * 同步微信员工、客户 | ||
263 | + * @throws \think\db\exception\DataNotFoundException | ||
264 | + * @throws \think\db\exception\ModelNotFoundException | ||
265 | + * @throws \think\exception\DbException | ||
266 | + * @throws \think\exception\PDOException | ||
267 | + */ | ||
268 | + public function synwx() | ||
269 | + { | ||
270 | + set_time_limit(0); | ||
271 | + $key = "work_weixin_set"; | ||
272 | + $settingModel = new \app\admin\model\facrm\Setting(); | ||
273 | + $row = $settingModel->where('key', $key)->cache(1800)->find(); | ||
274 | + if (!$row) { | ||
275 | + echo "企业微信未配置"; | ||
276 | + return; | ||
277 | + } | ||
278 | + $values = json_decode($row['values'], true);//获取器不知道为什么失效了 | ||
279 | + if (!$values) { | ||
280 | + echo "企业微信未配置1"; | ||
281 | + return; | ||
282 | + } | ||
283 | + | ||
284 | + | ||
285 | + $config = [ | ||
286 | + 'corp_id' => $values['corp_id'], | ||
287 | + 'secret' => $values['agent_secret'], | ||
288 | + 'agent_id' => $values['agent_id'], | ||
289 | + //'agent_secret' => $values['agent_secret'], | ||
290 | + ]; | ||
291 | + try { | ||
292 | + $app = Factory::work($config); | ||
293 | + $result = $app->user->getDetailedDepartmentUsers(1, true); | ||
294 | + } catch (\Exception $e) { | ||
295 | + $this->error($e->getMessage()); | ||
296 | + | ||
297 | + } | ||
298 | + if (!$result || $result['errcode'] != '0') { | ||
299 | + $errmsg = isset($result['errmsg']) ? $result['errmsg'] : 'null'; | ||
300 | + echo "获取失败:" . $errmsg; | ||
301 | + return; | ||
302 | + } | ||
303 | + $userlist = $result['userlist']; | ||
304 | + $result = 0; | ||
305 | + foreach ($userlist as $user) { | ||
306 | + //判断系统是否存在 | ||
307 | + $qywxUser = \app\admin\model\facrm\qywx\User::getUser($user['userid'], $values, $user); | ||
308 | + if ($qywxUser) $result++; | ||
309 | + } | ||
310 | + echo "同步更新企业微信员工{$result}条"; | ||
311 | + /*-----------同步员工end----------------*/ | ||
312 | + | ||
313 | + $this->synwxcustomer($values); | ||
314 | + return; | ||
315 | + | ||
316 | + | ||
317 | + } | ||
318 | + | ||
319 | + | ||
320 | + protected function synwxcustomer($values,$page=1,$next_cursor="",$is_action=true){ | ||
321 | + $c_config = [ | ||
322 | + 'corp_id' => $values['corp_id'], | ||
323 | + 'secret' => $values['customer_secret'], // 客户的 secret | ||
324 | + ]; | ||
325 | + $appc = Factory::work($c_config); | ||
326 | + $qywxUserModel = new \app\admin\model\facrm\qywx\User(); | ||
327 | + $userList = $qywxUserModel->page($page,100)->order('id asc')->column('admin_id','userid'); | ||
328 | + if (!$userList){ | ||
329 | + echo "同步客户完成"; | ||
330 | + return; | ||
331 | + } | ||
332 | + | ||
333 | + $contactsModel = new \app\admin\model\facrm\qywx\Contacts(); | ||
334 | + | ||
335 | + $externalcontact = new \addons\facrm\library\extend\easywechat\Externalcontact($appc); | ||
336 | + try { | ||
337 | + //批量查询客户详情 | ||
338 | + $externalList = $externalcontact->batch(array_keys($userList),$next_cursor,100); | ||
339 | + } catch (\Exception $e) { | ||
340 | + echo $e->getMessage(); | ||
341 | + } | ||
342 | + if (!$externalList || $externalList['errcode'] != '0' ){ | ||
343 | + echo $externalList['errmsg']; | ||
344 | + | ||
345 | + } | ||
346 | + if ($externalList['external_contact_list']&&count($externalList['external_contact_list'])>0){ | ||
347 | + $syn_number=count($externalList['external_contact_list']); | ||
348 | + foreach ($externalList['external_contact_list'] as $row) { | ||
349 | + $follow_user = $row['follow_info']; | ||
350 | + $admin_id=isset($userList[$follow_user['userid']])?$userList[$follow_user['userid']]:0; | ||
351 | + | ||
352 | + $contactsModel->getContacts($row, $values, ['admin_id' => $admin_id]); | ||
353 | + } | ||
354 | + if (isset($externalList['next_cursor'])&&$externalList['next_cursor']){ | ||
355 | + $syn_number+=$this->synwxcustomer($values,$page,$externalList['next_cursor'],false); | ||
356 | + } | ||
357 | + } | ||
358 | + if (!$is_action){ | ||
359 | + return $syn_number; | ||
360 | + } | ||
361 | + echo "本次同步更新{$syn_number}条客户数据"; | ||
362 | + return $this->synwxcustomer($values,$page+1); | ||
363 | + } | ||
364 | +} |
addons/facrm/controller/Captcha.php
0 → 100644
1 | +<?php | ||
2 | +// +---------------------------------------------------------------------- | ||
3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
4 | +// +---------------------------------------------------------------------- | ||
5 | +// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved. | ||
6 | +// +---------------------------------------------------------------------- | ||
7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
8 | +// +---------------------------------------------------------------------- | ||
9 | +// | Author: yunwuxin <448901948@qq.com> | ||
10 | +// +---------------------------------------------------------------------- | ||
11 | + | ||
12 | +namespace addons\facrm\controller; | ||
13 | + | ||
14 | +use addons\facrm\library\BackendApi; | ||
15 | +use think\Config; | ||
16 | +use think\captcha\Captcha as CaptchaLib; | ||
17 | + | ||
18 | +/** | ||
19 | + * 图片验证码 | ||
20 | + * Class Captcha | ||
21 | + * @package addons\facrm\controller | ||
22 | + */ | ||
23 | +class Captcha extends BackendApi | ||
24 | +{ | ||
25 | + protected $noNeedLogin = ['index']; | ||
26 | + public function index() | ||
27 | + { | ||
28 | + $id=request()->param('id'); | ||
29 | + $sid=request()->param('sid'); | ||
30 | + if (!$sid){ | ||
31 | + session_start(); | ||
32 | + session_id(); | ||
33 | + $this->success('',session_id()); | ||
34 | + }else{ | ||
35 | + session_id($sid); | ||
36 | + session_start(); | ||
37 | + } | ||
38 | + | ||
39 | + $captcha = new CaptchaLib((array)Config::get('captcha')); | ||
40 | + return $captcha->entry($id); | ||
41 | + } | ||
42 | +} |
addons/facrm/controller/Cloudcall.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | + | ||
4 | +namespace addons\facrm\controller; | ||
5 | + | ||
6 | + | ||
7 | + | ||
8 | +use fast\Date; | ||
9 | +use think\addons\Controller; | ||
10 | + | ||
11 | +/** | ||
12 | + * 云呼回调接口 | ||
13 | + * @icon fa fa-circle-o | ||
14 | + */ | ||
15 | +class Cloudcall extends Controller | ||
16 | +{ | ||
17 | + protected $cacheCallName = "cache_call_engine_name"; | ||
18 | + protected $calltypes = []; | ||
19 | + | ||
20 | + public function _initialize() | ||
21 | + { | ||
22 | + parent::_initialize(); | ||
23 | + $this->request->filter(['strip_tags']); | ||
24 | + | ||
25 | + } | ||
26 | + | ||
27 | + /** | ||
28 | + * 通话记录回调 | ||
29 | + * @ApiParams(name="engine", type="string", required=true, description="通道") | ||
30 | + * @ApiBody ("域名/addons/facrm/cloudcall/back?engine=通道(如Tycc100)") | ||
31 | + * @ApidBody | ||
32 | + */ | ||
33 | + public function back($engine=null) | ||
34 | + { | ||
35 | + $engine=!$engine?$this->request->request('engine'):$engine; | ||
36 | + $engine=!$engine?$this->request->route('engine'):""; | ||
37 | + if (!$engine){ | ||
38 | + $this->error("通道不存在"); | ||
39 | + } | ||
40 | + $this->setting = cache($this->cacheCallName.$engine); | ||
41 | + | ||
42 | + if (!$this->setting) { | ||
43 | + $this->key = "cloudcall"; | ||
44 | + $settingModel = new \app\admin\model\facrm\Setting(); | ||
45 | + $this->setting=$settingModel->where('key', "cloudcall".$engine)->find(); | ||
46 | + if (!$this->setting){ | ||
47 | + $this->error("通道不存在"); | ||
48 | + } | ||
49 | + $this->setting=$this->setting->toArray(); | ||
50 | + cache($this->cacheCallName.$engine, $this->setting, 86400);//缓存一天 | ||
51 | + } | ||
52 | + | ||
53 | + $this->setting['key'] = $this->setting['describe']; | ||
54 | + $this->setting = array_merge($this->setting, $this->setting['values']); | ||
55 | + $call= \addons\facrm\library\cloudcall\Call::instance($this->setting); | ||
56 | + $result=$call->back(); | ||
57 | + | ||
58 | + } | ||
59 | + | ||
60 | + | ||
61 | +} |
addons/facrm/controller/Index.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller; | ||
4 | + | ||
5 | +use addons\facrm\library\BackendApi; | ||
6 | +use addons\facrm\model\Admin as AdminModel; | ||
7 | +use app\admin\model\AdminLog; | ||
8 | +use think\Config; | ||
9 | +use think\Hook; | ||
10 | +use think\Validate; | ||
11 | + | ||
12 | +/** | ||
13 | + * 登录操作 | ||
14 | + * @internal | ||
15 | + */ | ||
16 | +class Index extends BackendApi | ||
17 | +{ | ||
18 | + | ||
19 | + protected $noNeedLogin = ['login', 'wxlogin','bind','mplogin']; | ||
20 | + protected $noNeedRight = ['logout','unbind','thirdlist']; | ||
21 | + protected $platforms =['admin_min','admin_mp'] ;//admin_min微信小程序登录标识 | ||
22 | + | ||
23 | + public function _initialize() | ||
24 | + { | ||
25 | + parent::_initialize(); | ||
26 | + //移除HTML标签 | ||
27 | + $this->request->filter('trim,strip_tags,htmlspecialchars'); | ||
28 | + } | ||
29 | + /** | ||
30 | + * 登录[帐号和密码] | ||
31 | + * @ApiMethod (post) | ||
32 | + * @ApiParams(name="username", type="string", required=true, description="帐号") | ||
33 | + * @ApiParams(name="password", type="string", required=true, description="密码") | ||
34 | + * @ApiParams(name="keeplogin", type="string", required=false, description="保持登录,暂时未做") | ||
35 | + */ | ||
36 | + public function login() | ||
37 | + { | ||
38 | + $username = $this->request->post('username'); | ||
39 | + $password = $this->request->post('password'); | ||
40 | + $keeplogin = $this->request->post('keeplogin'); | ||
41 | + $sid=$this->request->post('sid'); | ||
42 | + if ($sid){ | ||
43 | + session_id($sid); | ||
44 | + session_start(); | ||
45 | + } | ||
46 | + | ||
47 | + $rule = [ | ||
48 | + 'username' => 'require|length:3,30', | ||
49 | + 'password' => 'require|length:3,30', | ||
50 | + ]; | ||
51 | + $data = [ | ||
52 | + 'username' => $username, | ||
53 | + 'password' => $password, | ||
54 | + | ||
55 | + ]; | ||
56 | + if (Config::get('fastadmin.login_captcha')) { | ||
57 | + $rule['captcha'] = 'require|captcha'; | ||
58 | + $data['captcha'] = $this->request->post('captcha'); | ||
59 | + } | ||
60 | + $validate = new Validate($rule, [], ['username' => __('Username'), 'password' => __('Password'), 'captcha' => __('Captcha')]); | ||
61 | + $result = $validate->check($data); | ||
62 | + if (!$result) { | ||
63 | + | ||
64 | + $this->error($validate->getError()); | ||
65 | + } | ||
66 | + | ||
67 | + AdminLog::setTitle(__('移动端帐号登录')); | ||
68 | + $result = $this->auth->login($username, $password, $keeplogin ? 86400 : 0); | ||
69 | + if ($result === true) { | ||
70 | + $admin = $this->auth->getAdmin(); | ||
71 | + if ($admin) { | ||
72 | + Hook::listen("admin_login_after", $this->request); | ||
73 | + $this->success(__("登录成功!"), [ | ||
74 | + 'token' => $admin->token, | ||
75 | + 'id' => $admin->id, | ||
76 | + 'username' => $admin->username, | ||
77 | + 'nickname' => $admin->nickname, | ||
78 | + 'avatar' => cdnurl($admin->avatar, true), | ||
79 | + ]); | ||
80 | + } | ||
81 | + | ||
82 | + | ||
83 | + } | ||
84 | + $msg = $this->auth->getError(); | ||
85 | + $msg = $msg ? $msg : __('Username or password is incorrect'); | ||
86 | + $this->error($msg); | ||
87 | + | ||
88 | + | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * 小程序微信登录 | ||
93 | + * @ApiMethod (post) | ||
94 | + * @ApiParams(name="code", type="string", required=true, description="code") | ||
95 | + * @ApiParams(name="encrypted_data", type="string", required=true, description="encrypted_data") | ||
96 | + * @ApiParams(name="iv", type="string", required=true, description="iv") | ||
97 | + */ | ||
98 | + public function wxlogin() | ||
99 | + { | ||
100 | + | ||
101 | + $platform='admin_min'; | ||
102 | + $model = new AdminModel(); | ||
103 | + $post = $this->request->post(); | ||
104 | + $third = get_addon_info('third'); | ||
105 | + if (!$third || $third['state']!=1) { | ||
106 | + $this->error(__("请先安装第三方登录插件")); | ||
107 | + } | ||
108 | + $data = $model->minLogin($post); | ||
109 | + if (!$data) { | ||
110 | + $this->error($model->getError()); | ||
111 | + } | ||
112 | + | ||
113 | + $data['openid'] = $data['openId']; | ||
114 | + $data['unionId'] =isset($data['unionId'])? $data['unionId']:''; | ||
115 | + $data['access_token'] = $data['refresh_token'] = $post['code']; | ||
116 | + $data['expires_in'] = 0; | ||
117 | + $data['userinfo']['nickname'] = $data['nickName']; | ||
118 | + $data['userinfo']['avatar'] = $data['avatarUrl']; | ||
119 | + $third = $model->connects($platform, $data); | ||
120 | + | ||
121 | + AdminLog::setTitle(__('小程序登录')); | ||
122 | + if ($third) { | ||
123 | + if (isset($third->user_id)&&$third->user_id) { | ||
124 | + $admin = $this->auth->direct($third->user_id); | ||
125 | + if ($admin) { | ||
126 | + Hook::listen("admin_login_after", $this->request); | ||
127 | + $this->success(__("登录成功!"), [ | ||
128 | + 'token' => $admin->token, | ||
129 | + 'id' => $admin->id, | ||
130 | + 'username' => $admin->username, | ||
131 | + 'nickname' => $admin->nickname, | ||
132 | + 'avatar' => cdnurl($admin->avatar, true), | ||
133 | + ]); | ||
134 | + } | ||
135 | + $this->error(__($this->auth->getError())); | ||
136 | + } else { | ||
137 | + //绑定帐号 | ||
138 | + $this->error(__("跳转到绑定帐号"), ['refresh_token' => $third->refresh_token]); | ||
139 | + } | ||
140 | + } | ||
141 | + $this->error(__("登录失败,请重试")); | ||
142 | + } | ||
143 | + | ||
144 | + /** | ||
145 | + * 微信公众号登录 | ||
146 | + * @ApiMethod (get) | ||
147 | + * @ApiParams(name="code", type="string", required=true, description="code") | ||
148 | + */ | ||
149 | + public function mplogin(){ | ||
150 | + $platform='admin_mp'; | ||
151 | + $model = new AdminModel(); | ||
152 | + $get = $this->request->get(); | ||
153 | + $third = get_addon_info('third'); | ||
154 | + if (!$third || $third['state']!=1) { | ||
155 | + $this->error(__("请先安装第三方登录插件")); | ||
156 | + } | ||
157 | + $data = $model->mpLogin($get); | ||
158 | + if (!$data) { | ||
159 | + $this->error($model->getError()); | ||
160 | + } | ||
161 | + if (!isset($data['original']['openid'])){ | ||
162 | + $this->error(__("获取微信登录信息失败")); | ||
163 | + } | ||
164 | + | ||
165 | + $data_param['openid'] = $data['original']['openid']; | ||
166 | + $data_param['unionId'] =isset($data['original']['unionId'])? $data['original']['unionId']:''; | ||
167 | + $data_param['expires_in'] =3600; | ||
168 | + $data_param['userinfo']['nickname'] = $data['nickname']; | ||
169 | + $data_param['userinfo']['avatar'] = $data['avatar']; | ||
170 | + $data_param['access_token'] = $data['access_token']; | ||
171 | + $data_param['refresh_token'] = $data['refresh_token']; | ||
172 | + | ||
173 | + $third = $model->connects($platform, $data_param); | ||
174 | + | ||
175 | + AdminLog::setTitle(__('公众号登录')); | ||
176 | + if ($third) { | ||
177 | + if (isset($third->user_id)&&$third->user_id) { | ||
178 | + $admin = $this->auth->direct($third->user_id); | ||
179 | + if ($admin) { | ||
180 | + Hook::listen("admin_login_after", $this->request); | ||
181 | + $this->success(__("登录成功!"), [ | ||
182 | + 'token' => $admin->token, | ||
183 | + 'id' => $admin->id, | ||
184 | + 'username' => $admin->username, | ||
185 | + 'nickname' => $admin->nickname, | ||
186 | + 'avatar' => cdnurl($admin->avatar, true), | ||
187 | + ]); | ||
188 | + } | ||
189 | + $this->error(__($this->auth->getError())); | ||
190 | + } else { | ||
191 | + //绑定帐号 | ||
192 | + $this->error(__("跳转到绑定帐号"), ['refresh_token' => $third->refresh_token]); | ||
193 | + } | ||
194 | + } | ||
195 | + $this->error(__("登录失败,请重试")); | ||
196 | + } | ||
197 | + | ||
198 | + | ||
199 | + /** | ||
200 | + * 绑定原有帐号 | ||
201 | + * @ApiMethod (POST) | ||
202 | + * @ApiParams(name="username", type="string", required=true, description="帐号") | ||
203 | + * @ApiParams(name="password", type="string", required=true, description="密码") | ||
204 | + * @ApiParams(name="keeplogin", type="string", required=false, description="保持登录,暂时未做") | ||
205 | + * @ApiParams(name="platform", type="string", required=false, description="绑定平台admin_min:小程序 admin_mp:公众号") | ||
206 | + * @ApiParams (name="refresh_token", type="string", required=true, sample="",description="绑定凭证") | ||
207 | + * @ApiReturnParams (name="token", type="string", required=false, sample="0",description="登录凭证") | ||
208 | + * admin_mp | ||
209 | + * @return array | ||
210 | + */ | ||
211 | + public function bind() | ||
212 | + { | ||
213 | + $platform = $this->request->post('platform','admin_min'); | ||
214 | + $refresh_token = $this->request->post('refresh_token'); | ||
215 | + $username = $this->request->post('username'); | ||
216 | + $password = $this->request->post('password'); | ||
217 | + $keeplogin = $this->request->post('keeplogin'); | ||
218 | + $sid=$this->request->post('sid'); | ||
219 | + if ($sid){ | ||
220 | + session_id($sid); | ||
221 | + session_start(); | ||
222 | + } | ||
223 | + if (!$refresh_token) { | ||
224 | + $this->error("获取登录信息错误"); | ||
225 | + } | ||
226 | + $rule = [ | ||
227 | + 'username' => 'require|length:3,30', | ||
228 | + 'password' => 'require|length:3,30', | ||
229 | + ]; | ||
230 | + $data = [ | ||
231 | + 'username' => $username, | ||
232 | + 'password' => $password, | ||
233 | + | ||
234 | + ]; | ||
235 | + if (Config::get('fastadmin.login_captcha')) { | ||
236 | + $rule['captcha'] = 'require|captcha'; | ||
237 | + $data['captcha'] = $this->request->post('captcha'); | ||
238 | + } | ||
239 | + $validate = new Validate($rule, [], ['username' => __('用户名'), 'password' => __('密码'), 'captcha' => __('验证码')]); | ||
240 | + $result = $validate->check($data); | ||
241 | + if (!$result) { | ||
242 | + $this->error($validate->getError()); | ||
243 | + } | ||
244 | + | ||
245 | + $third = \addons\third\model\Third::where('refresh_token', $refresh_token)->where('platform', $platform)->find(); | ||
246 | + if (!$third) { | ||
247 | + $this->error(__('绑定的数据不存在')); | ||
248 | + } | ||
249 | + if ($third->user_id > 0) { | ||
250 | + $this->error(__('已绑定过')); | ||
251 | + } | ||
252 | + if ($third['updatetime'] < (time() - 1800)) { | ||
253 | + $third->delete(); | ||
254 | + $this->error(__('请求已经过期,请重试!')); | ||
255 | + } | ||
256 | + | ||
257 | + AdminLog::setTitle(__('小程序绑定登录')); | ||
258 | + $result = $this->auth->login($username, $password, $keeplogin ? 86400 : 0); | ||
259 | + if ($result === true) { | ||
260 | + $admin = $this->auth->getAdmin(); | ||
261 | + if ($admin) { | ||
262 | + Hook::listen("admin_login_after", $this->request); | ||
263 | + | ||
264 | + $third['user_id'] = $admin->id; | ||
265 | + $third->save(); | ||
266 | + $this->success(__("登录成功!"), [ | ||
267 | + 'token' => $admin->token, | ||
268 | + 'id' => $admin->id, | ||
269 | + 'username' => $admin->username, | ||
270 | + 'nickname' => $admin->nickname, | ||
271 | + 'avatar' => cdnurl($admin->avatar, true), | ||
272 | + ]); | ||
273 | + } | ||
274 | + } | ||
275 | + $msg = $this->auth->getError(); | ||
276 | + $msg = $msg ? $msg : __('Username or password is incorrect'); | ||
277 | + $this->error($msg); | ||
278 | + | ||
279 | + } | ||
280 | + | ||
281 | + /** | ||
282 | + * 解绑 | ||
283 | + *@ApiParams(name="platform", type="string", required=true, description="平台:admin_min:小程序 admin_mp:公众号") | ||
284 | + */ | ||
285 | + public function unbind(){ | ||
286 | + $platform = $this->request->post('platform','admin_min'); | ||
287 | + if (!in_array($platform,$this->platforms)){ | ||
288 | + $this->error(__('平台不存在')); | ||
289 | + } | ||
290 | + $third = \addons\third\model\Third::where('user_id', $this->auth->id)->where('platform', $platform)->find(); | ||
291 | + if (!$third) { | ||
292 | + $this->error(__('绑定的数据不存在')); | ||
293 | + } | ||
294 | + $third->delete(); | ||
295 | + $this->success(__("解绑成功!")); | ||
296 | + } | ||
297 | + | ||
298 | + /** | ||
299 | + * 获取第三方登录绑定列表 | ||
300 | + */ | ||
301 | + public function thirdlist(){ | ||
302 | + $third = get_addon_info('third'); | ||
303 | + if (!$third || $third['state']!=1) { | ||
304 | + $this->error(__("请先安装第三方登录插件")); | ||
305 | + } | ||
306 | + $thirdlist = \addons\third\model\Third::where('user_id', $this->auth->id) | ||
307 | + ->field('id,platform,openname,logintime') | ||
308 | + ->where('platform', 'in',$this->platforms)->select(); | ||
309 | + $this->success('',$thirdlist); | ||
310 | + | ||
311 | + } | ||
312 | + | ||
313 | + /** | ||
314 | + * 退出登录 | ||
315 | + */ | ||
316 | + public function logout() | ||
317 | + { | ||
318 | + $this->auth->logout(); | ||
319 | + $this->success(__("退出成功")); | ||
320 | + } | ||
321 | + | ||
322 | +} |
addons/facrm/controller/Order.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | + | ||
4 | +namespace addons\facrm\controller; | ||
5 | + | ||
6 | + | ||
7 | +use addons\third\model\Third; | ||
8 | + | ||
9 | +use fast\Date; | ||
10 | +use think\addons\Controller; | ||
11 | +use think\Exception; | ||
12 | +use think\Response; | ||
13 | + | ||
14 | + | ||
15 | +/** | ||
16 | + * 订单支付 | ||
17 | + * @icon fa fa-circle-o | ||
18 | + */ | ||
19 | +class Order extends Controller | ||
20 | +{ | ||
21 | + | ||
22 | + protected $layout = 'default'; | ||
23 | + protected $pay_config = []; | ||
24 | + protected $key = "payonline"; | ||
25 | + | ||
26 | + public function _initialize() | ||
27 | + { | ||
28 | + parent::_initialize(); | ||
29 | + $epayinfo = get_addon_info('epay'); | ||
30 | + if (!$epayinfo || !$epayinfo['state']){ | ||
31 | + $this->error(__("微信支付宝插件未安装或未启用")); | ||
32 | + } | ||
33 | + $this->view->assign("epayinfo", $epayinfo); | ||
34 | + | ||
35 | + $this->request->filter(['strip_tags']); | ||
36 | + $settingModel = new \app\admin\model\facrm\Setting(); | ||
37 | + $this->pay_config =\addons\facrm\library\Order::getPayConfig(); | ||
38 | + if (!$this->pay_config) { | ||
39 | + $this->error(__("未配置收款")); | ||
40 | + } | ||
41 | + } | ||
42 | + | ||
43 | + | ||
44 | + /** | ||
45 | + * 支付订单[收款] | ||
46 | + */ | ||
47 | + public function pay() | ||
48 | + { | ||
49 | + | ||
50 | + | ||
51 | + if (!$this->pay_config['values']['online_pay']) { | ||
52 | + $this->error(__("未配置收款")); | ||
53 | + } | ||
54 | + | ||
55 | + //获取收款单信息 | ||
56 | + $pay_token = $this->request->request('pay_token');//访问凭证 | ||
57 | + if (!$pay_token) { | ||
58 | + $this->error(__("访问有误")); | ||
59 | + } | ||
60 | + $receivablesModel = new \app\admin\model\facrm\contract\Receivables(); | ||
61 | + $payInfo = $receivablesModel->where('pay_token', $pay_token)->find(); | ||
62 | + $tempvars=$payInfo->toArray(); | ||
63 | + | ||
64 | + $check_data=\addons\facrm\library\Order::checkPay($payInfo, 'pay',$this->pay_config); | ||
65 | + if ($check_data['code']!=1){ | ||
66 | + $this->error(__($check_data['msg'])); | ||
67 | + } | ||
68 | + | ||
69 | + | ||
70 | + $agreement = __($this->pay_config['values']['agreement'],$tempvars); | ||
71 | + $this->view->assign("row", $payInfo); | ||
72 | + $this->view->assign("agreement", $agreement); | ||
73 | + $this->view->assign("title", __("支付订单")); | ||
74 | + return $this->view->fetch(); | ||
75 | + | ||
76 | + | ||
77 | + } | ||
78 | + | ||
79 | + /** | ||
80 | + * 合同续费 | ||
81 | + */ | ||
82 | + public function renew() | ||
83 | + { | ||
84 | + //获取合同信息 | ||
85 | + $pay_token = $this->request->request('pay_token'); | ||
86 | + if (!$pay_token) { | ||
87 | + $this->error(__("访问有误")); | ||
88 | + } | ||
89 | + | ||
90 | + //判断是否开启续费功能 | ||
91 | + if ($this->pay_config['values']['renew_pay'] != 1) { | ||
92 | + $this->error(__("未开启续费功能")); | ||
93 | + } | ||
94 | + | ||
95 | + | ||
96 | + $contractModel = new \app\admin\model\facrm\Contract(); | ||
97 | + $contractInfo = $contractModel->where('renewtoken', $pay_token)->find(); | ||
98 | + $check_data=\addons\facrm\library\Order::checkPay($contractInfo, 'renew',$this->pay_config); | ||
99 | + if ($check_data['code']!=1){ | ||
100 | + $this->error(__($check_data['msg'])); | ||
101 | + } | ||
102 | + | ||
103 | + //判断合同是否设定了续费单价, | ||
104 | + if ($contractInfo['renewmoeny']<=0){ | ||
105 | + $contractInfo['renewmoeny']=bcdiv(($contractInfo['money']*$this->pay_config['values']['renew_percentage']),100,2); | ||
106 | + } | ||
107 | + $pay_config=$this->pay_config['values']; | ||
108 | + $pay_config['r_agreement'] = __($pay_config['r_agreement'], $contractInfo->toArray()); | ||
109 | + | ||
110 | + | ||
111 | + $this->view->assign("pay_config", $pay_config); | ||
112 | + $this->view->assign("row", $contractInfo); | ||
113 | + $this->view->assign("title", __("续费")); | ||
114 | + return $this->view->fetch(); | ||
115 | + | ||
116 | + } | ||
117 | + | ||
118 | + | ||
119 | + /** | ||
120 | + * 提交支付订单 | ||
121 | + * @return \addons\epay\library\Collection|\addons\epay\library\RedirectResponse|\addons\epay\library\Response | ||
122 | + * @throws \think\db\exception\DataNotFoundException | ||
123 | + * @throws \think\db\exception\ModelNotFoundException | ||
124 | + * @throws \think\exception\DbException | ||
125 | + */ | ||
126 | + public function submit() | ||
127 | + { | ||
128 | + $pay_token = request()->request('pay_token'); | ||
129 | + if (!$pay_token) $this->error("付款单不存在"); | ||
130 | + | ||
131 | + $info = get_addon_info('epay'); | ||
132 | + if (!$info || !$info['state']) { | ||
133 | + $this->error('请在后台插件管理安装微信支付宝整合插件后重试'); | ||
134 | + } | ||
135 | + $paytype = $this->request->request('paytype', 'wechat'); | ||
136 | + $ordertype = $this->request->request('ordertype', 'pay'); | ||
137 | + $method = $this->request->request('method'); | ||
138 | + $appid = $this->request->request('appid');//APP的应用ID | ||
139 | + $returnurl = $this->request->request('returnurl', '', 'trim'); | ||
140 | + $number = $this->request->request('number', '1', 'intval');//下单数量,只有续费才有效果 | ||
141 | + | ||
142 | + | ||
143 | + //公众号和小程序 | ||
144 | + $openid = ''; | ||
145 | + if (in_array($method, ['miniapp', 'mp'])) { | ||
146 | + $third = Third::where('platform', 'wechat')->where('apptype', $method)->where('user_id', $this->auth->id)->find(); | ||
147 | + if (!$third) { | ||
148 | + $this->error("未找到登录用户信息", 'bind'); | ||
149 | + } | ||
150 | + $openid = $third['openid']; | ||
151 | + } | ||
152 | + try { | ||
153 | + $response = \addons\facrm\library\Order::submit($pay_token, $ordertype,$paytype, $method, $openid, $appid, $returnurl, ['number' => $number]); | ||
154 | + return $response; | ||
155 | + } catch (\Exception $e) { | ||
156 | + $this->error($e->getMessage()); | ||
157 | + } | ||
158 | + | ||
159 | + } | ||
160 | + | ||
161 | + /** | ||
162 | + * 企业支付通知和回调 | ||
163 | + */ | ||
164 | + public function epay() | ||
165 | + { | ||
166 | + \think\Log::write(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '_________', 'error'); | ||
167 | + | ||
168 | + $type = $this->request->param('type'); | ||
169 | + $paytype = $this->request->param('paytype'); | ||
170 | + if ($type == 'notify') { | ||
171 | + \think\Log::write('__验证开始__', 'error'); | ||
172 | + $pay = \addons\epay\library\Service::checkNotify($paytype); | ||
173 | + if (!$pay) { | ||
174 | + \think\Log::write('__签名错误_', 'error'); | ||
175 | + echo '签名错误'; | ||
176 | + return; | ||
177 | + } | ||
178 | + $data = $pay->verify(); | ||
179 | + | ||
180 | + /* //调试 | ||
181 | + $data=array( | ||
182 | + 'total_amount'=>800, | ||
183 | + 'out_trade_no'=>'20220519113008000000003943', | ||
184 | + 'total_fee'=>80000, | ||
185 | + );*/ | ||
186 | + try { | ||
187 | + $payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100; | ||
188 | + \think\Log::write('__进入支付_', 'error'); | ||
189 | + \addons\facrm\library\Order::settle($data['out_trade_no'], $payamount); | ||
190 | + } catch (Exception $e) { | ||
191 | + \think\Log::write($e->getMessage() . '__支付异常报错_', 'error'); | ||
192 | + } | ||
193 | + echo $pay->success(); | ||
194 | + } else { | ||
195 | + $pay = \addons\epay\library\Service::checkReturn($paytype); | ||
196 | + if (!$pay) { | ||
197 | + $this->error('签名错误'); | ||
198 | + } | ||
199 | + //微信支付没有返回链接 | ||
200 | + if ($pay === true) { | ||
201 | + $this->success("请返回网站查看支付状态!", ""); | ||
202 | + } | ||
203 | + | ||
204 | + //你可以在这里定义你的提示信息,但切记不可在此编写逻辑 | ||
205 | + $this->success("请返回网站查看支付状态!", url("user/index")); | ||
206 | + } | ||
207 | + return; | ||
208 | + } | ||
209 | + | ||
210 | + | ||
211 | + /** | ||
212 | + * 生成二维码 | ||
213 | + */ | ||
214 | + public function qrcode() | ||
215 | + { | ||
216 | + $text = $this->request->get('text', 'hello world'); | ||
217 | + | ||
218 | + //如果有安装二维码插件,则调用插件的生成方法 | ||
219 | + if (class_exists("\addons\qrcode\library\Service") && get_addon_info('qrcode')['state']) { | ||
220 | + $qrCode = \addons\qrcode\library\Service::qrcode(['text' => $text]); | ||
221 | + $response = Response::create()->header("Content-Type", "image/png"); | ||
222 | + | ||
223 | + header('Content-Type: ' . $qrCode->getContentType()); | ||
224 | + $response->content($qrCode->writeString()); | ||
225 | + return $response; | ||
226 | + } else { | ||
227 | + $qr = \addons\facrm\library\QRCode::getMinimumQRCode($text); | ||
228 | + $im = $qr->createImage(8, 5); | ||
229 | + header("Content-type: image/png"); | ||
230 | + imagepng($im); | ||
231 | + imagedestroy($im); | ||
232 | + return; | ||
233 | + } | ||
234 | + } | ||
235 | + | ||
236 | + | ||
237 | +} |
addons/facrm/controller/Qywx.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | + | ||
4 | +namespace addons\facrm\controller; | ||
5 | + | ||
6 | + | ||
7 | +use app\admin\model\Admin; | ||
8 | +use EasyWeChat\Factory; | ||
9 | +use think\addons\Controller; | ||
10 | +use think\Hook; | ||
11 | +use think\Log; | ||
12 | +use think\Session; | ||
13 | +use app\admin\model\facrm\qywx\User as QywxUser; | ||
14 | +use EasyWeChat\Kernel\Support; | ||
15 | +use addons\facrm\library\BackendApi; | ||
16 | + | ||
17 | +/** | ||
18 | + * 企业微信通信管理 | ||
19 | + * @icon fa fa-circle-o | ||
20 | + */ | ||
21 | +class Qywx extends BackendApi | ||
22 | +{ | ||
23 | + protected $app = null;//EasyWeChat 实列 | ||
24 | + protected $config = array();//企业微信配置 | ||
25 | + protected $noNeedRight = ['*']; | ||
26 | + protected $noNeedLogin = ['connect','login','wxlogin']; | ||
27 | + | ||
28 | + public function _initialize() | ||
29 | + { | ||
30 | + //跨域请求检测 | ||
31 | + check_cors_request(); | ||
32 | + parent::_initialize(); | ||
33 | + $this->request->filter(['strip_tags']); | ||
34 | + | ||
35 | + $key = "work_weixin_set"; | ||
36 | + $settingModel = new \app\admin\model\facrm\Setting(); | ||
37 | + $row = $settingModel->where('key', $key)->find(); | ||
38 | + if (!$row) $this->error(__("企业微信未配置")); | ||
39 | + $this->config = json_decode($row['values'], true);//获取器不知道为什么失效了 | ||
40 | + if (!$this->config) $this->error(__("企业微信未配置1")); | ||
41 | + | ||
42 | + } | ||
43 | + | ||
44 | + /** | ||
45 | + * 微信验证 | ||
46 | + * @ApiInternal | ||
47 | + */ | ||
48 | + public function connect() | ||
49 | + { | ||
50 | + | ||
51 | + $config = [ | ||
52 | + 'corp_id' => $this->config['corp_id'], | ||
53 | + 'agent_id' => $this->config['agent_id'], | ||
54 | + 'secret' => $this->config['agent_secret'], | ||
55 | + 'token' => $this->config['customer_callback_token'], | ||
56 | + 'aes_key' => $this->config['EncodongAESKey'], | ||
57 | + ]; | ||
58 | + $app = Factory::work($config); | ||
59 | + $app->server->push(function($message){ | ||
60 | + $res= \addons\facrm\library\qywx\Event::execute($message); | ||
61 | + }); | ||
62 | + $response = $app->server->serve(); | ||
63 | + $response->send(); | ||
64 | + | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * 企业微信H5登录 | ||
69 | + * @ApiParams(name="code", type="string", required=true, description="post请求的时候需要") | ||
70 | + * @ApiParams(name="url", type="string", required=true, description="url") | ||
71 | + * @ApiBody ("get是获取一些基本配置") | ||
72 | + * | ||
73 | + */ | ||
74 | + public function login(){ | ||
75 | + $app_ag_config = [ | ||
76 | + 'corp_id' => $this->config['corp_id'], | ||
77 | + 'agent_id' => $this->config['agent_id'], | ||
78 | + 'secret' => $this->config['agent_secret'], | ||
79 | + ]; | ||
80 | + | ||
81 | + if (request()->isGet()){ | ||
82 | + $url = $this->request->param('url'); | ||
83 | + $config = [ | ||
84 | + 'corp_id' => $this->config['corp_id'], | ||
85 | + 'agent_id' => $this->config['agent_id'], | ||
86 | + 'secret' => $this->config['customer_secret'], | ||
87 | + ]; | ||
88 | + $this->app = $app = Factory::work($config); | ||
89 | + $wx_config = ($app->jssdk->buildConfig(['updateAppMessageShareData', 'updateTimelineShareData'], $debug = false, $beta = false, $json = true, $openTagList = [])); | ||
90 | + | ||
91 | + $this->app = $app = Factory::work($app_ag_config); | ||
92 | + $supportExtend=new \addons\facrm\library\extend\easywechat\SupportExtend($app); | ||
93 | + $ag_config = $supportExtend->buildAgentConfig( | ||
94 | + ['getCurExternalContact'], | ||
95 | + $this->config['agent_id'], | ||
96 | + $debug = false, | ||
97 | + $beta = false, | ||
98 | + $json = true, | ||
99 | + $openTagList = [], | ||
100 | + $url | ||
101 | + ); | ||
102 | + | ||
103 | + $this->success('',['wx_config'=>json_decode($wx_config,true),'ag_config'=>json_decode($ag_config,true)]); | ||
104 | + | ||
105 | + }else{ | ||
106 | + | ||
107 | + $app = Factory::work($app_ag_config); | ||
108 | + $user = $app->oauth->detailed()->user(); | ||
109 | + // 获取用户信息 | ||
110 | + $userid = $user->getId(); // 对应企业微信英文名(userid) | ||
111 | + if (!$userid) $this->error(__("获取企业微信信息失败")); | ||
112 | + | ||
113 | + $loca_user = QywxUser::getUser($userid); | ||
114 | + if (!$loca_user) { | ||
115 | + //不存在就调用接口去获取 | ||
116 | + $c_config = [ | ||
117 | + 'corp_id' => $this->config['corp_id'], | ||
118 | + 'secret' => $this->config['contacts_secret'], // 通讯录的 secret | ||
119 | + ]; | ||
120 | + $contacts = Factory::work($c_config); | ||
121 | + $qywx_user = $contacts->user->get($userid); | ||
122 | + | ||
123 | + if (!$qywx_user || $qywx_user['errcode'] != '0') $this->error(__("获取企业微信信息失败")); | ||
124 | + $loca_user = QywxUser::getUser($userid, $this->config, $qywx_user); | ||
125 | + } | ||
126 | + | ||
127 | + if (!$loca_user || !$loca_user['admin_id']) { | ||
128 | + $this->error(__("企业微信登录失败")); | ||
129 | + } | ||
130 | + | ||
131 | + $admin = $this->auth->direct($loca_user['admin_id']); | ||
132 | + if ($admin) { | ||
133 | + Hook::listen("admin_login_after", $this->request); | ||
134 | + $this->success(__("登录成功!"), [ | ||
135 | + 'token' => $admin->token, | ||
136 | + 'id' => $admin->id, | ||
137 | + 'username' => $admin->username, | ||
138 | + 'nickname' => $admin->nickname, | ||
139 | + 'avatar' => cdnurl($admin->avatar, true), | ||
140 | + ]); | ||
141 | + } | ||
142 | + $this->error(__($this->auth->getError())); | ||
143 | + | ||
144 | + } | ||
145 | + $this->error(__('登录失败')); | ||
146 | + | ||
147 | + } | ||
148 | + | ||
149 | + /** | ||
150 | + * 企业微信小程序登录 | ||
151 | + * @ApiBody ("") | ||
152 | + * | ||
153 | + */ | ||
154 | + public function wxlogin(){ | ||
155 | + $config = [ | ||
156 | + 'corp_id' => $this->config['corp_id'], | ||
157 | + 'agent_id' => $this->config['agent_id'], | ||
158 | + 'secret' => $this->config['agent_secret'], | ||
159 | + ]; | ||
160 | + | ||
161 | + $app = Factory::work($config); | ||
162 | + | ||
163 | + $miniProgram = $app->miniProgram(); | ||
164 | + | ||
165 | + $res = $miniProgram->auth->session("js-code"); | ||
166 | + | ||
167 | + if ($res&&isset($res['userid'])){ | ||
168 | + $userid = $res['userid']; // 对应企业微信英文名(userid) | ||
169 | + if (!$userid) $this->error(__("获取企业微信信息失败")); | ||
170 | + | ||
171 | + $loca_user = QywxUser::getUser($userid); | ||
172 | + if (!$loca_user) { | ||
173 | + //不存在就调用接口去获取 | ||
174 | + $c_config = [ | ||
175 | + 'corp_id' => $this->config['corp_id'], | ||
176 | + 'secret' => $this->config['contacts_secret'], // 通讯录的 secret | ||
177 | + ]; | ||
178 | + $contacts = Factory::work($c_config); | ||
179 | + $qywx_user = $contacts->user->get($userid); | ||
180 | + | ||
181 | + if (!$qywx_user || $qywx_user['errcode'] != '0') $this->error(__("获取企业微信信息失败")); | ||
182 | + $loca_user = QywxUser::getUser($userid, $this->config, $qywx_user); | ||
183 | + } | ||
184 | + | ||
185 | + if (!$loca_user || !$loca_user['admin_id']) { | ||
186 | + $this->error(__("企业微信登录失败")); | ||
187 | + } | ||
188 | + | ||
189 | + $admin = $this->auth->direct($loca_user['admin_id']); | ||
190 | + if ($admin) { | ||
191 | + Hook::listen("admin_login_after", $this->request); | ||
192 | + $this->success(__("登录成功!"), [ | ||
193 | + 'token' => $admin->token, | ||
194 | + 'id' => $admin->id, | ||
195 | + 'username' => $admin->username, | ||
196 | + 'nickname' => $admin->nickname, | ||
197 | + 'avatar' => cdnurl($admin->avatar, true), | ||
198 | + ]); | ||
199 | + } | ||
200 | + $this->error(__($this->auth->getError())); | ||
201 | + } | ||
202 | + | ||
203 | + $this->error(__("获取企业微信信息失败2")); | ||
204 | + } | ||
205 | + | ||
206 | + | ||
207 | + /** | ||
208 | + * 获取客户ID | ||
209 | + * @ApiParams(name="userid", type="string", required=true, description="企业微信客户") | ||
210 | + * @ApiBody ("get是获取一些基本配置") | ||
211 | + * @Internal | ||
212 | + */ | ||
213 | + public function getCustomerId() | ||
214 | + { | ||
215 | + $admin = $this->auth->getUserInfo(); | ||
216 | + if (!$admin) $this->error(__("未登录")); | ||
217 | + | ||
218 | + $external_userid = $this->request->param('userid'); | ||
219 | + if (!$external_userid) $this->error(__("userid不能为空")); | ||
220 | + | ||
221 | + //获取本地微信外部联系人customer_id; | ||
222 | + $contactsModel = new \app\admin\model\facrm\qywx\Contacts(); | ||
223 | + | ||
224 | + $qywxContacts = $contactsModel->getContacts($external_userid, $this->config, ['admin_id' => $admin['id']]); | ||
225 | + if (!$qywxContacts) { | ||
226 | + $this->error(__("获取企业客户信息失败")); | ||
227 | + } | ||
228 | + $this->success('', $qywxContacts->customer_id); | ||
229 | + } | ||
230 | + | ||
231 | + | ||
232 | +} |
addons/facrm/controller/auth/Admin.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller\auth; | ||
4 | + | ||
5 | +use addons\facrm\library\BackendApi; | ||
6 | +use app\admin\model\AuthGroup; | ||
7 | +use app\admin\model\AuthGroupAccess; | ||
8 | +use fast\Random; | ||
9 | +use fast\Tree; | ||
10 | +use think\Validate; | ||
11 | + | ||
12 | +/** | ||
13 | + * 管理员管理 | ||
14 | + * | ||
15 | + * @icon fa fa-users | ||
16 | + * @remark 一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成 | ||
17 | + */ | ||
18 | +class Admin extends BackendApi | ||
19 | +{ | ||
20 | + | ||
21 | + /** | ||
22 | + * @var \app\admin\model\Admin | ||
23 | + */ | ||
24 | + protected $model = null; | ||
25 | + protected $selectpageFields = 'id,username,nickname,avatar'; | ||
26 | + protected $searchFields = 'id,username,nickname'; | ||
27 | + protected $childrenGroupIds = []; | ||
28 | + protected $childrenAdminIds = []; | ||
29 | + protected $groupdata=[]; | ||
30 | + protected $noNeedRight = ['getGroupdata']; | ||
31 | + public function _initialize() | ||
32 | + { | ||
33 | + parent::_initialize(); | ||
34 | + $this->model = model('\app\admin\model\Admin'); | ||
35 | + | ||
36 | + $this->childrenAdminIds = $this->auth->getChildrenAdminIds(true); | ||
37 | + $this->childrenGroupIds = $this->auth->getChildrenGroupIds(true); | ||
38 | + | ||
39 | + $groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray(); | ||
40 | + | ||
41 | + Tree::instance()->init($groupList); | ||
42 | + | ||
43 | + if ($this->auth->isSuperAdmin()) { | ||
44 | + $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); | ||
45 | + foreach ($result as $k => $v) { | ||
46 | + $this->groupdata[$v['id']] = $v['name']; | ||
47 | + } | ||
48 | + } else { | ||
49 | + $result = []; | ||
50 | + $groups = $this->auth->getGroups(); | ||
51 | + | ||
52 | + foreach ($groups as $m => $n) { | ||
53 | + $result[$n['id']] =__($n['name']); | ||
54 | + $childlist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['id'])); | ||
55 | + foreach ($childlist as $k => $v) { | ||
56 | + $result[$v['id']] = $v['name']; | ||
57 | + } | ||
58 | + | ||
59 | + } | ||
60 | + $this->groupdata = $result; | ||
61 | + } | ||
62 | + | ||
63 | + } | ||
64 | + | ||
65 | + /** | ||
66 | + * 查看 | ||
67 | + */ | ||
68 | + public function index() | ||
69 | + { | ||
70 | + //设置过滤方法 | ||
71 | + $this->request->filter(['strip_tags', 'trim']); | ||
72 | + //如果发送的来源是Selectpage,则转发到Selectpage | ||
73 | + if ($this->request->request('keyField')) { | ||
74 | + return $this->selectpage(); | ||
75 | + } | ||
76 | + $childrenGroupIds = $this->childrenGroupIds; | ||
77 | + $groupName = AuthGroup::where('id', 'in', $childrenGroupIds) | ||
78 | + ->column('id,name'); | ||
79 | + $authGroupList = AuthGroupAccess::where('group_id', 'in', $childrenGroupIds) | ||
80 | + ->field('uid,group_id') | ||
81 | + ->select(); | ||
82 | + | ||
83 | + $adminGroupName = []; | ||
84 | + foreach ($authGroupList as $k => $v) { | ||
85 | + if (isset($groupName[$v['group_id']])) { | ||
86 | + $adminGroupName[$v['uid']][$v['group_id']] = $groupName[$v['group_id']]; | ||
87 | + } | ||
88 | + } | ||
89 | + $groups = $this->auth->getGroups(); | ||
90 | + foreach ($groups as $m => $n) { | ||
91 | + $adminGroupName[$this->auth->id][$n['id']] = $n['name']; | ||
92 | + } | ||
93 | + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); | ||
94 | + | ||
95 | + $list = $this->model | ||
96 | + ->where($where) | ||
97 | + ->where('id', 'in', $this->childrenAdminIds) | ||
98 | + ->field(['password', 'salt', 'token'], true) | ||
99 | + ->order($sort, $order) | ||
100 | + ->paginate($limit); | ||
101 | + | ||
102 | + foreach ($list as $k => &$v) { | ||
103 | + $groups = isset($adminGroupName[$v['id']]) ? $adminGroupName[$v['id']] : []; | ||
104 | + $v['groups'] = implode(',', array_keys($groups)); | ||
105 | + $v['groups_text'] = implode(',', array_values($groups)); | ||
106 | + } | ||
107 | + unset($v); | ||
108 | + $result = array("rows" => $list); | ||
109 | + $this->success('', $result); | ||
110 | + | ||
111 | + } | ||
112 | + | ||
113 | + /** | ||
114 | + * 获取员工组 | ||
115 | + */ | ||
116 | + public function getGroupdata() | ||
117 | + { | ||
118 | + $this->success('',$this->groupdata); | ||
119 | + } | ||
120 | + /** | ||
121 | + * 添加 | ||
122 | + */ | ||
123 | + public function add() | ||
124 | + { | ||
125 | + if ($this->request->isPost()) { | ||
126 | + | ||
127 | + $params = $this->request->post(); | ||
128 | + if ($params) { | ||
129 | + if (!Validate::is($params['password'], '\S{6,16}')) { | ||
130 | + $this->error(__("Please input correct password")); | ||
131 | + } | ||
132 | + $params['salt'] = Random::alnum(); | ||
133 | + $params['password'] = md5(md5($params['password']) . $params['salt']); | ||
134 | + $params['avatar'] = '/assets/img/avatar.png'; //设置新管理员默认头像。 | ||
135 | + $result = $this->model->validate('\app\admin\validate\Admin.add')->allowField(true)->save($params); | ||
136 | + if ($result === false) { | ||
137 | + $this->error($this->model->getError()); | ||
138 | + } | ||
139 | + $group = $this->request->post("group/a"); | ||
140 | + //过滤不允许的组别,避免越权 | ||
141 | + $group = array_intersect($this->childrenGroupIds, $group); | ||
142 | + $dataset = []; | ||
143 | + foreach ($group as $value) { | ||
144 | + $dataset[] = ['uid' => $this->model->id, 'group_id' => $value]; | ||
145 | + } | ||
146 | + model('\app\admin\model\AuthGroupAccess')->saveAll($dataset); | ||
147 | + $this->success(); | ||
148 | + } | ||
149 | + | ||
150 | + } | ||
151 | + $this->error(); | ||
152 | + } | ||
153 | + | ||
154 | + /** | ||
155 | + * 编辑 | ||
156 | + * @ApiParams(name="id", type="int", required=true, description="管理员id") | ||
157 | + * @ApiBody("get获取,post提交修改") | ||
158 | + */ | ||
159 | + public function edit() | ||
160 | + { | ||
161 | + $ids = $this->request->request('id', '', 'intval'); | ||
162 | + if (!$ids) { | ||
163 | + $this->error(__('No Results were found')); | ||
164 | + } | ||
165 | + | ||
166 | + $row = $this->model->get(['id' => $ids]); | ||
167 | + if (!$row) { | ||
168 | + $this->error(__('No Results were found')); | ||
169 | + } | ||
170 | + if (!in_array($row->id, $this->childrenAdminIds)) { | ||
171 | + $this->error(__('You have no permission')); | ||
172 | + } | ||
173 | + if ($this->request->isPost()) { | ||
174 | + | ||
175 | + $params = $this->request->post(); | ||
176 | + if ($params) { | ||
177 | + if ($params['password']) { | ||
178 | + if (!Validate::is($params['password'], '\S{6,16}')) { | ||
179 | + $this->error(__("Please input correct password")); | ||
180 | + } | ||
181 | + $params['salt'] = Random::alnum(); | ||
182 | + $params['password'] = md5(md5($params['password']) . $params['salt']); | ||
183 | + } else { | ||
184 | + unset($params['password'], $params['salt']); | ||
185 | + } | ||
186 | + //这里需要针对username和email做唯一验证 | ||
187 | + $adminValidate = \think\Loader::validate('\app\admin\validate\Admin'); | ||
188 | + $adminValidate->rule([ | ||
189 | + 'username' => 'require|regex:\w{3,12}|unique:admin,username,' . $row->id, | ||
190 | + 'email' => 'require|email|unique:admin,email,' . $row->id, | ||
191 | + 'password' => 'regex:\S{32}', | ||
192 | + ]); | ||
193 | + $result = $row->validate('\app\admin\validate\Admin.edit')->allowField(true)->save($params); | ||
194 | + | ||
195 | + if ($result === false) { | ||
196 | + $this->error($row->getError()); | ||
197 | + } | ||
198 | + | ||
199 | + // 先移除所有权限 | ||
200 | + model('\app\admin\model\AuthGroupAccess')->where('uid', $row->id)->delete(); | ||
201 | + | ||
202 | + $group = $this->request->post("group/a"); | ||
203 | + | ||
204 | + // 过滤不允许的组别,避免越权 | ||
205 | + $group = array_intersect($this->childrenGroupIds, $group); | ||
206 | + | ||
207 | + $dataset = []; | ||
208 | + foreach ($group as $value) { | ||
209 | + $dataset[] = ['uid' => $row->id, 'group_id' => $value]; | ||
210 | + } | ||
211 | + model('\app\admin\model\AuthGroupAccess')->saveAll($dataset); | ||
212 | + $this->success(); | ||
213 | + } | ||
214 | + $this->error(); | ||
215 | + } | ||
216 | + $grouplist = $this->auth->getGroups($row['id']); | ||
217 | + $groupids = []; | ||
218 | + foreach ($grouplist as $k => $v) { | ||
219 | + $groupids[] = $v['id']; | ||
220 | + } | ||
221 | + $this->success('',['row'=>$row,'groupids'=>$groupids]); | ||
222 | + } | ||
223 | + | ||
224 | + /** | ||
225 | + * 删除 | ||
226 | + * @ApiParams(name="ids", type="int", required=true, description="管理员id") | ||
227 | + */ | ||
228 | + public function del() | ||
229 | + { | ||
230 | + $ids = $this->request->request('ids', '', 'intval'); | ||
231 | + if (!$ids) { | ||
232 | + $this->error(__('No Results were found')); | ||
233 | + } | ||
234 | + if (!$this->request->isPost()) { | ||
235 | + $this->error(__("Invalid parameters")); | ||
236 | + } | ||
237 | + $ids = $ids ? $ids : $this->request->post("ids"); | ||
238 | + if ($ids) { | ||
239 | + $ids = array_intersect($this->childrenAdminIds, array_filter(explode(',', $ids))); | ||
240 | + // 避免越权删除管理员 | ||
241 | + $childrenGroupIds = $this->childrenGroupIds; | ||
242 | + $adminList = $this->model->where('id', 'in', $ids)->where('id', 'in', function ($query) use ($childrenGroupIds) { | ||
243 | + $query->name('auth_group_access')->where('group_id', 'in', $childrenGroupIds)->field('uid'); | ||
244 | + })->select(); | ||
245 | + if ($adminList) { | ||
246 | + $deleteIds = []; | ||
247 | + foreach ($adminList as $k => $v) { | ||
248 | + $deleteIds[] = $v->id; | ||
249 | + } | ||
250 | + $deleteIds = array_values(array_diff($deleteIds, [$this->auth->id])); | ||
251 | + if ($deleteIds) { | ||
252 | + $this->model->destroy($deleteIds); | ||
253 | + model('\app\admin\model\AuthGroupAccess')->where('uid', 'in', $deleteIds)->delete(); | ||
254 | + $this->success(); | ||
255 | + } | ||
256 | + } | ||
257 | + } | ||
258 | + $this->error(__('You have no permission')); | ||
259 | + } | ||
260 | + | ||
261 | + /** | ||
262 | + * 下拉搜索 | ||
263 | + */ | ||
264 | + public function selectpage() | ||
265 | + { | ||
266 | + $this->dataLimit = 'auth'; | ||
267 | + $this->dataLimitField = 'id'; | ||
268 | + return parent::selectpage(); | ||
269 | + } | ||
270 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller\facrm; | ||
4 | + | ||
5 | +use app\admin\model\AuthGroup; | ||
6 | +use addons\facrm\library\BackendApi; | ||
7 | +use fast\Tree; | ||
8 | +use think\Db; | ||
9 | +use think\Exception; | ||
10 | + | ||
11 | +/** | ||
12 | + * 业绩目标 | ||
13 | + * | ||
14 | + */ | ||
15 | +class Achievement extends BackendApi | ||
16 | +{ | ||
17 | + | ||
18 | + /** | ||
19 | + * @var \app\admin\model\AuthGroup | ||
20 | + */ | ||
21 | + protected $model = null; | ||
22 | + //当前登录管理员所有子组别 | ||
23 | + protected $childrenGroupIds = []; | ||
24 | + protected $childrenAdminIds = []; | ||
25 | + //当前组别列表数据 | ||
26 | + protected $groupdata = []; | ||
27 | + protected $groupList = []; | ||
28 | + //无需要权限判断的方法 | ||
29 | + protected $noNeedRight = ['roletree']; | ||
30 | + | ||
31 | + public function _initialize() | ||
32 | + { | ||
33 | + parent::_initialize(); | ||
34 | + $this->request->filter(['strip_tags']); | ||
35 | + $this->model = new AuthGroup(); | ||
36 | + | ||
37 | + $this->childrenGroupIds = $this->auth->getChildrenGroupIds(true); | ||
38 | + $this->childrenAdminIds = $this->auth->getChildrenAdminIds(true); | ||
39 | + $this->groupList = $groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray(); | ||
40 | + | ||
41 | + Tree::instance()->init($groupList); | ||
42 | + $result = []; | ||
43 | + if ($this->auth->isSuperAdmin()) { | ||
44 | + $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); | ||
45 | + } else { | ||
46 | + $groups = $this->auth->getGroups(); | ||
47 | + foreach ($groups as $m => $n) { | ||
48 | + $result = array_merge($result, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['pid']))); | ||
49 | + } | ||
50 | + } | ||
51 | + $groupName = []; | ||
52 | + foreach ($result as $k => $v) { | ||
53 | + $groupName[$v['id']] = $v['name']; | ||
54 | + } | ||
55 | + | ||
56 | + $this->groupdata = $groupName; | ||
57 | + } | ||
58 | + | ||
59 | + protected $temp_achievement = [ | ||
60 | + 'type' => 2, | ||
61 | + 'type_id' => '', | ||
62 | + 'year' => '', | ||
63 | + 'january' => '', | ||
64 | + 'february' => '', | ||
65 | + 'march' => '', | ||
66 | + 'april' => '', | ||
67 | + 'may' => '', | ||
68 | + 'june' => '', | ||
69 | + 'july' => '', | ||
70 | + 'august' => '', | ||
71 | + 'september' => '', | ||
72 | + 'october' => '', | ||
73 | + 'november' => '', | ||
74 | + 'december' => '', | ||
75 | + 'yeartarget' => '', | ||
76 | + ]; | ||
77 | + | ||
78 | + /** | ||
79 | + * 查看列表 | ||
80 | + * @ApiMethod (get) | ||
81 | + */ | ||
82 | + public function index() | ||
83 | + { | ||
84 | + $achievement = new \app\admin\model\facrm\Achievement(); | ||
85 | + $filter = $this->request->get("filter", ''); | ||
86 | + $filter = (array)json_decode($filter, true); | ||
87 | + $filter_w = []; | ||
88 | + if (isset($filter['search_time'])) { | ||
89 | + $filter_w['year'] = $filter['search_time']; | ||
90 | + unset($filter['search_time']); | ||
91 | + } else { | ||
92 | + $filter_w['year'] = date('Y', time()); | ||
93 | + } | ||
94 | + if (isset($filter['config'])) { | ||
95 | + $filter_w['config'] = $filter['config']; | ||
96 | + unset($filter['config']); | ||
97 | + } else { | ||
98 | + $filter_w['config'] = 1; | ||
99 | + } | ||
100 | + $this->request->get(['filter' => json_encode($filter)]); | ||
101 | + | ||
102 | + | ||
103 | + if (isset($filter['group_id'])) { | ||
104 | + $list = AuthGroup::all($filter['group_id']); | ||
105 | + } else { | ||
106 | + $list = AuthGroup::all(array_keys($this->groupdata)); | ||
107 | + } | ||
108 | + $list = collection($list)->toArray(); | ||
109 | + $groupList = []; | ||
110 | + foreach ($list as $k => $v) { | ||
111 | + $groupList[$v['id']] = $v; | ||
112 | + } | ||
113 | + $list = []; | ||
114 | + foreach ($this->groupdata as $k => $v) { | ||
115 | + | ||
116 | + if (isset($groupList[$k])) { | ||
117 | + $groupList[$k]['name'] = $v; | ||
118 | + $groupList[$k]['achievement'] = $achievement->where('type', 2)->where($filter_w)->where('type_id', $k)->find(); | ||
119 | + $groupList[$k]['achievement'] = $groupList[$k]['achievement'] ?: $this->temp_achievement; | ||
120 | + $list[] = $groupList[$k]; | ||
121 | + | ||
122 | + } | ||
123 | + } | ||
124 | + $total = count($list); | ||
125 | + $result = array("total" => $total, "rows" => $list, "extend" => ['year' => $filter_w['year'], 'config' => isset($filter_w['config']) ? $filter_w['config'] : '']); | ||
126 | + | ||
127 | + $this->success('',$result); | ||
128 | + | ||
129 | + | ||
130 | + } | ||
131 | + | ||
132 | + | ||
133 | + /** | ||
134 | + * 员工业绩列表 | ||
135 | + * @ApiMethod (get) | ||
136 | + */ | ||
137 | + public function admin() | ||
138 | + { | ||
139 | + $achievement = new \app\admin\model\facrm\Achievement(); | ||
140 | + //设置过滤方法 | ||
141 | + $filter = $this->request->get("filter", ''); | ||
142 | + $filter = (array)json_decode($filter, true); | ||
143 | + $filter_w = []; | ||
144 | + if (isset($filter['search_time'])) { | ||
145 | + $filter_w['year'] = $filter['search_time']; | ||
146 | + unset($filter['search_time']); | ||
147 | + } else { | ||
148 | + $filter_w['year'] = date('Y', time()); | ||
149 | + } | ||
150 | + if (isset($filter['config'])) { | ||
151 | + $filter_w['config'] = $filter['config']; | ||
152 | + unset($filter['config']); | ||
153 | + } else { | ||
154 | + $filter_w['config'] = 1; | ||
155 | + } | ||
156 | + | ||
157 | + | ||
158 | + $this->model =new \app\admin\model\Admin(); | ||
159 | + $childrenAdminIds = $this->getFilterChildrenAdminIds($filter); | ||
160 | + | ||
161 | + if ($childrenAdminIds) { | ||
162 | + $this->childrenAdminIds = $childrenAdminIds; | ||
163 | + } | ||
164 | + if (isset($filter['group_id'])) { | ||
165 | + unset($filter['group_id']); | ||
166 | + } | ||
167 | + | ||
168 | + $this->request->get(['filter' => json_encode($filter)]); | ||
169 | + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); | ||
170 | + $list = $this->model | ||
171 | + ->where($where) | ||
172 | + ->where('id', 'in', $this->childrenAdminIds) | ||
173 | + ->field(['password', 'salt', 'token'], true) | ||
174 | + ->order($sort, $order) | ||
175 | + ->paginate($limit); | ||
176 | + $this->temp_achievement['type'] = 3; | ||
177 | + foreach ($list as $k => &$row) { | ||
178 | + $row['achievement'] = $achievement->where('type', 3)->where($filter_w)->where('type_id', $row['id'])->find(); | ||
179 | + $row['achievement'] = $row['achievement'] ?: $this->temp_achievement; | ||
180 | + | ||
181 | + } | ||
182 | + unset($v); | ||
183 | + $result = array("total" => $list->total(), "rows" => $list->items(), "extend" => ['year' => $filter_w['year'], 'config' => isset($filter_w['config']) ? $filter_w['config'] : '']); | ||
184 | + $this->success('',$result); | ||
185 | + } | ||
186 | + | ||
187 | + /** | ||
188 | + * 团队业绩编辑(单条) | ||
189 | + * @ApiMethod (POST) | ||
190 | + */ | ||
191 | + public function edit() | ||
192 | + { | ||
193 | + $param = $this->request->param('row/a'); | ||
194 | + $field = $param['field']; | ||
195 | + if (!isset($param['config']) || !in_array($param['config'], [1, 2])) { | ||
196 | + $this->error(__("业绩方式有误")); | ||
197 | + } | ||
198 | + if (!isset($param['year']) && $param['year'] < 2000) { | ||
199 | + $this->error(__("年份有误")); | ||
200 | + } | ||
201 | + if (!isset($param['group_id']) && $param['group_id'] < 0) { | ||
202 | + $this->error(__("权限组有误")); | ||
203 | + } | ||
204 | + $where = [ | ||
205 | + 'type' => 2, | ||
206 | + 'type_id' => $param['group_id'], | ||
207 | + 'year' => $param['year'], | ||
208 | + 'config' => $param['config'], | ||
209 | + ]; | ||
210 | + $achievement = new \app\admin\model\facrm\Achievement(); | ||
211 | + $row = $achievement->where($where)->find(); | ||
212 | + | ||
213 | + if (!is_numeric($param[$field]) || $param[$field] < 0) { | ||
214 | + $this->error(__("请输入数字")); | ||
215 | + } | ||
216 | + if (!$row) { | ||
217 | + //添加一条新记录 | ||
218 | + $this->temp_achievement['type_id'] = $param['group_id']; | ||
219 | + $this->temp_achievement['year'] = $param['year']; | ||
220 | + $this->temp_achievement['config'] = $param['config']; | ||
221 | + $row = $achievement->create($this->temp_achievement); | ||
222 | + | ||
223 | + if (!$row) { | ||
224 | + $this->error(__("插入数据失败")); | ||
225 | + } | ||
226 | + $row = $achievement->find($row->id); | ||
227 | + } | ||
228 | + | ||
229 | + try { | ||
230 | + | ||
231 | + $old_val = $row->$field; | ||
232 | + if ($old_val == $param[$field]) { | ||
233 | + $this->error(__("没有修改")); | ||
234 | + } elseif ($old_val > $param[$field]) { | ||
235 | + $row->yeartarget = $row->yeartarget - ($old_val - $param[$field]); | ||
236 | + } elseif ($old_val < $param[$field]) { | ||
237 | + $row->yeartarget = $row->yeartarget + ($param[$field] - $old_val); | ||
238 | + } | ||
239 | + $row->$field = $param[$field]; | ||
240 | + $row->config = $param['config']; | ||
241 | + $row->save(); | ||
242 | + } catch (\Exception $e) { | ||
243 | + $this->error($e->getMessage()); | ||
244 | + } | ||
245 | + $this->success(); | ||
246 | + } | ||
247 | + | ||
248 | + /** | ||
249 | + * 成员业绩编辑(单条) | ||
250 | + * @param null $ids | ||
251 | + * @ApiMethod (POST) | ||
252 | + */ | ||
253 | + public function aedit() | ||
254 | + { | ||
255 | + $param = $this->request->param('row/a'); | ||
256 | + $field = $param['field']; | ||
257 | + if (!isset($param['year']) && $param['year'] < 2000) { | ||
258 | + $this->error(__("年份有误")); | ||
259 | + } | ||
260 | + if (!isset($param['admin_id']) && $param['admin_id'] < 0) { | ||
261 | + $this->error(__("权限组有误")); | ||
262 | + } | ||
263 | + if (!isset($param['config']) || !in_array($param['config'], [1, 2])) { | ||
264 | + $this->error(__("业绩方式有误")); | ||
265 | + } | ||
266 | + $where = [ | ||
267 | + 'type' => 3, | ||
268 | + 'type_id' => $param['admin_id'], | ||
269 | + 'year' => $param['year'], | ||
270 | + 'config' => $param['config'], | ||
271 | + ]; | ||
272 | + $achievement = new \app\admin\model\facrm\Achievement(); | ||
273 | + $row = $achievement->where($where)->find(); | ||
274 | + if (!is_numeric($param[$field]) || $param[$field] < 0) { | ||
275 | + $this->error(__("请输入数字")); | ||
276 | + } | ||
277 | + if (!$row) { | ||
278 | + //添加一条新记录 | ||
279 | + $this->temp_achievement['type_id'] = $param['admin_id']; | ||
280 | + $this->temp_achievement['year'] = $param['year']; | ||
281 | + $this->temp_achievement['type'] = 3; | ||
282 | + $this->temp_achievement['config'] = $param['config']; | ||
283 | + $row = $achievement->create($this->temp_achievement); | ||
284 | + | ||
285 | + if (!$row) { | ||
286 | + $this->error(__("插入数据失败")); | ||
287 | + } | ||
288 | + $row = $achievement->find($row->id); | ||
289 | + } | ||
290 | + | ||
291 | + try { | ||
292 | + | ||
293 | + $old_val = $row->$field; | ||
294 | + if ($old_val == $param[$field]) { | ||
295 | + $this->error(__("没有修改")); | ||
296 | + } elseif ($old_val > $param[$field]) { | ||
297 | + $row->yeartarget = $row->yeartarget - ($old_val - $param[$field]); | ||
298 | + } elseif ($old_val < $param[$field]) { | ||
299 | + $row->yeartarget = $row->yeartarget + ($param[$field] - $old_val); | ||
300 | + } | ||
301 | + $row->$field = $param[$field]; | ||
302 | + $row->save(); | ||
303 | + | ||
304 | + } catch (\Exception $e) { | ||
305 | + $this->error($e->getMessage()); | ||
306 | + } | ||
307 | + $this->success(); | ||
308 | + } | ||
309 | + | ||
310 | + /** | ||
311 | + * 团队批量设置 | ||
312 | + */ | ||
313 | + public function batchTeam(){ | ||
314 | + if ($this->request->isPost()) { | ||
315 | + $param = $this->request->param('row/a'); | ||
316 | + if (!isset($param['config']) || !in_array($param['config'], [1, 2])) { | ||
317 | + $this->error(__("业绩方式有误")); | ||
318 | + } | ||
319 | + if (!isset($param['year']) && $param['year'] < 2000) { | ||
320 | + $this->error(__("年份有误")); | ||
321 | + } | ||
322 | + if (!isset($param['group_id']) && $param['group_id'] < 0) { | ||
323 | + $this->error(__("部门有误")); | ||
324 | + } | ||
325 | + $where = [ | ||
326 | + 'type' => 2, | ||
327 | + 'year' => $param['year'], | ||
328 | + 'config' => $param['config'], | ||
329 | + ]; | ||
330 | + | ||
331 | + $result=false; | ||
332 | + | ||
333 | + if ($param['group_id']==0){ | ||
334 | + //全部 | ||
335 | + unset($param['group_id']); | ||
336 | + foreach ($this->groupList as $g){ | ||
337 | + $achievement = new \app\admin\model\facrm\Achievement(); | ||
338 | + $where['type_id']=$g['id']; | ||
339 | + $row = $achievement->where($where)->find(); | ||
340 | + $this->temp_achievement=array_merge($this->temp_achievement,$param); | ||
341 | + $this->temp_achievement['type_id'] = $where['type_id']; | ||
342 | + $this->temp_achievement['year'] = $where['year']; | ||
343 | + if (!$row) { | ||
344 | + //添加一条新记录 | ||
345 | + $result=$achievement->create($this->temp_achievement); | ||
346 | + }else{ | ||
347 | + $result=$row->save($this->temp_achievement); | ||
348 | + } | ||
349 | + } | ||
350 | + | ||
351 | + $this->success(); | ||
352 | + | ||
353 | + }else{ | ||
354 | + $achievement = new \app\admin\model\facrm\Achievement(); | ||
355 | + //某一个部门 | ||
356 | + $where['type_id']=$param['group_id']; | ||
357 | + unset($param['group_id']); | ||
358 | + | ||
359 | + $row = $achievement->where($where)->find(); | ||
360 | + $this->temp_achievement=array_merge($this->temp_achievement,$param); | ||
361 | + $this->temp_achievement['type_id'] = $where['type_id']; | ||
362 | + $this->temp_achievement['year'] = $where['year']; | ||
363 | + if (!$row) { | ||
364 | + //添加一条新记录 | ||
365 | + $result=$achievement->create($this->temp_achievement); | ||
366 | + }else{ | ||
367 | + $result=$row->save($this->temp_achievement); | ||
368 | + } | ||
369 | + } | ||
370 | + if ($result){ | ||
371 | + $this->success(); | ||
372 | + }else{ | ||
373 | + $this->error(__("添加失败")); | ||
374 | + } | ||
375 | + | ||
376 | + | ||
377 | + } | ||
378 | + $this->error(__("提交方式错误")); | ||
379 | + } | ||
380 | + | ||
381 | + /** | ||
382 | + * 成员批量设置 | ||
383 | + */ | ||
384 | + public function batchAdmin(){ | ||
385 | + if ($this->request->isPost()) { | ||
386 | + $param = $this->request->param('row/a'); | ||
387 | + if (!isset($param['config']) || !in_array($param['config'], [1, 2])) { | ||
388 | + $this->error(__("业绩方式有误")); | ||
389 | + } | ||
390 | + if (!isset($param['year']) && $param['year'] < 2000) { | ||
391 | + $this->error(__("年份有误")); | ||
392 | + } | ||
393 | + if (!isset($param['admin_id'])) { | ||
394 | + $this->error(__("员工有误")); | ||
395 | + } | ||
396 | + $where = [ | ||
397 | + 'type' => 3, | ||
398 | + 'year' => $param['year'], | ||
399 | + 'config' => $param['config'], | ||
400 | + ]; | ||
401 | + | ||
402 | + $result=false; | ||
403 | + if ($param['admin_id']){ | ||
404 | + $this->childrenAdminIds=explode(",",$param['admin_id']); | ||
405 | + } | ||
406 | + //全部 | ||
407 | + unset($param['admin_id']); | ||
408 | + $lists = \app\admin\model\Admin::where('id', 'in', $this->childrenAdminIds) | ||
409 | + ->field(['password', 'salt', 'token'], true) | ||
410 | + ->select(); | ||
411 | + | ||
412 | + | ||
413 | + foreach ($lists as $g){ | ||
414 | + $achievement = new \app\admin\model\facrm\Achievement(); | ||
415 | + $where['type_id']=$g['id']; | ||
416 | + $row = $achievement->where($where)->find(); | ||
417 | + $this->temp_achievement=array_merge($this->temp_achievement,$param); | ||
418 | + $this->temp_achievement['type_id'] = $where['type_id']; | ||
419 | + $this->temp_achievement['year'] = $where['year']; | ||
420 | + $this->temp_achievement['type']=$where['type']; | ||
421 | + if (!$row) { | ||
422 | + //添加一条新记录 | ||
423 | + $result=$achievement->create($this->temp_achievement); | ||
424 | + }else{ | ||
425 | + $result=$row->isUpdate(true)->save($this->temp_achievement); | ||
426 | + } | ||
427 | + } | ||
428 | + | ||
429 | + $this->success(); | ||
430 | + } | ||
431 | + | ||
432 | + $this->error(__("提交方式错误")); | ||
433 | + } | ||
434 | + | ||
435 | + | ||
436 | + | ||
437 | + /** | ||
438 | + * 过滤查找子用户 | ||
439 | + * @param $filter | ||
440 | + * @return array|void | ||
441 | + */ | ||
442 | + protected function getFilterChildrenAdminIds($filter) | ||
443 | + { | ||
444 | + $childrenAdminIds = []; | ||
445 | + if (isset($filter['group_id'])) { | ||
446 | + $childrenAdminIds = []; | ||
447 | + if ($filter['group_id'] > 0) { | ||
448 | + Tree::instance()->init($this->groupList); | ||
449 | + $groupIds = Tree::instance()->getChildrenIds($filter['group_id'], true); | ||
450 | + | ||
451 | + $authGroupList = \app\admin\model\AuthGroupAccess:: | ||
452 | + field('uid,group_id') | ||
453 | + ->where('group_id', 'in', $groupIds) | ||
454 | + ->select(); | ||
455 | + foreach ($authGroupList as $k => $v) { | ||
456 | + if (in_array($v['uid'], $childrenAdminIds)) continue; | ||
457 | + $childrenAdminIds[] = $v['uid']; | ||
458 | + } | ||
459 | + if (!$childrenAdminIds) { | ||
460 | + | ||
461 | + $this->error("该组下面没有成员"); | ||
462 | + } | ||
463 | + } | ||
464 | + } | ||
465 | + return $childrenAdminIds; | ||
466 | + } | ||
467 | +} |
addons/facrm/controller/facrm/Backlog.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller\facrm; | ||
4 | + | ||
5 | +use addons\facrm\library\BackendApi; | ||
6 | +use think\Db; | ||
7 | +use think\Exception; | ||
8 | + | ||
9 | + | ||
10 | +/** | ||
11 | + * 待办事项 | ||
12 | + */ | ||
13 | +class Backlog extends BackendApi | ||
14 | +{ | ||
15 | + | ||
16 | + protected $model = null; | ||
17 | + /** | ||
18 | + * 快速搜索时执行查找的字段 | ||
19 | + */ | ||
20 | + protected $searchFields = 'customer_id,name,mobile,telephone'; | ||
21 | + protected $childrenAdminIds = []; | ||
22 | + | ||
23 | + public function _initialize() | ||
24 | + { | ||
25 | + parent::_initialize(); | ||
26 | + $this->request->filter(['strip_tags']); | ||
27 | + | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * 待审批列表 | ||
32 | + * @ApiParams(name="types", type="string", required=true, description="contract合同审批,receivables回款审批,invoice发票审批") | ||
33 | + */ | ||
34 | + public function index() | ||
35 | + { | ||
36 | + $types = $this->request->request('types', "contract"); | ||
37 | + $filter_w = []; | ||
38 | + if(!$model_str=\app\admin\model\facrm\Flow::getModelStr($types)){ | ||
39 | + $this->error(__("审核类型有误")); | ||
40 | + } | ||
41 | + | ||
42 | + $this->model = model($model_str); | ||
43 | + //$filter_w[]=['exp','FIND_IN_SET('. $this->auth->id.',flow_admin_id)']; | ||
44 | + // $filter_w[]=['exp','FIND_IN_SET(2,flow_admin_id)']; | ||
45 | + $filter_w['check_status'] = ['in', [0, 1]]; | ||
46 | + | ||
47 | + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); | ||
48 | + | ||
49 | + $total = $this->model | ||
50 | + ->where($where) | ||
51 | + ->where($filter_w) | ||
52 | + ->where('', 'exp', 'FIND_IN_SET(' . $this->auth->id . ',flow_admin_id)') | ||
53 | + ->order($sort, $order)->fetchSql(false) | ||
54 | + ->count(); | ||
55 | + $this->model | ||
56 | + ->where($where) | ||
57 | + ->where($filter_w) | ||
58 | + ->where('', 'exp', 'FIND_IN_SET(' . $this->auth->id . ',flow_admin_id)'); | ||
59 | + | ||
60 | + switch ($types) { | ||
61 | + case 'receivables': | ||
62 | + $this->model->with([ | ||
63 | + 'createUser' => function ($user) { | ||
64 | + $user->field('id,username,nickname'); | ||
65 | + }, | ||
66 | + 'customer' => function ($customer) { | ||
67 | + $customer->field('id,name'); | ||
68 | + }, | ||
69 | + 'contract' => function ($customer) { | ||
70 | + $customer->field('id,name,number'); | ||
71 | + }, | ||
72 | + ]); | ||
73 | + break; | ||
74 | + case "contract": | ||
75 | + $this->model->with([ | ||
76 | + 'createUser' => function ($user) { | ||
77 | + $user->field('id,username,nickname'); | ||
78 | + }, | ||
79 | + 'orderAdmin' => function ($user) { | ||
80 | + $user->field('id,username,nickname'); | ||
81 | + }, | ||
82 | + 'customer' => function ($customer) { | ||
83 | + $customer->field('id,name'); | ||
84 | + }, | ||
85 | + ]); | ||
86 | + break; | ||
87 | + case "invoice": | ||
88 | + $this->model->with([ | ||
89 | + 'createUser' => function ($user) { | ||
90 | + $user->field('id,username,nickname'); | ||
91 | + }, | ||
92 | + 'contract' => function ($user) { | ||
93 | + $user->field('id,number,name'); | ||
94 | + }, | ||
95 | + 'customer' => function ($customer) { | ||
96 | + $customer->field('id,name'); | ||
97 | + }, | ||
98 | + ]); | ||
99 | + break; | ||
100 | + | ||
101 | + } | ||
102 | + | ||
103 | + | ||
104 | + $list = $this->model->order($sort, $order) | ||
105 | + ->limit($offset, $limit)->fetchSql(false) | ||
106 | + ->select(); | ||
107 | + $result = array("rows" => $list); | ||
108 | + | ||
109 | + $this->success('', $result); | ||
110 | + | ||
111 | + } | ||
112 | + | ||
113 | + /** | ||
114 | + * 审批 | ||
115 | + * @ApiParams(name="types", type="string", required=true, description="contract合同审批,receivables回款审批") | ||
116 | + * @ApiParams(name="id", type="int", required=true, description="对应的待审批id") | ||
117 | + * @ApiParams(name="type", type="string", required=true, description="reject驳回,【审批的时候才需要】") | ||
118 | + * @ApiParams(name="next_admin_id", type="string", required=true, description="下个审批人,多个逗号隔开,如果是选择审批的话,需要结束就不要传【审批的时候才需要】") | ||
119 | + * @ApiParams(name="remark", type="string", required=true, description="备注,理由都是这个字段,【审批的时候才需要】") | ||
120 | + * @ApiBody ("get是获取审批信息,post是审批") | ||
121 | + */ | ||
122 | + public function verify() | ||
123 | + { | ||
124 | + $types = $this->request->request('types', "contract"); | ||
125 | + $ids = $this->request->request('id', "0",'intval'); | ||
126 | + | ||
127 | + if(!$model_str=\app\admin\model\facrm\Flow::getModelStr($types)){ | ||
128 | + $this->error(__("审核类型有误")); | ||
129 | + } | ||
130 | + | ||
131 | + $this->model = model($model_str); | ||
132 | + $Log = model('\app\admin\model\facrm\flow\Log'); | ||
133 | + $row = $this->model->get($ids); | ||
134 | + if (!$row) { | ||
135 | + $this->error(__('No Results were found')); | ||
136 | + } | ||
137 | + | ||
138 | + if ($row->check_status == [0, 1]) { | ||
139 | + $this->error(__('不是待审核')); | ||
140 | + } | ||
141 | + | ||
142 | + if (!in_array($this->auth->id, explode(',', $row->flow_admin_id))) { | ||
143 | + $this->error(__('您没有权限审核')); | ||
144 | + } | ||
145 | + | ||
146 | + $flow = model('\app\admin\model\facrm\Flow'); | ||
147 | + $flow_r = $flow->where('types', $types)->where("status", 1) | ||
148 | + ->where('id', $row->flow_id)->find(); | ||
149 | + | ||
150 | + if (!$flow_r) { | ||
151 | + $row->check_status=3; | ||
152 | + $row->flow_id=0; | ||
153 | + $row->flow_admin_id=$row->check_admin_id="";//已审批的人清空 | ||
154 | + $row->save(); | ||
155 | + $this->error(__('审核流程不存在,已经直接驳回!')); | ||
156 | + } | ||
157 | + | ||
158 | + $flow_r->step = $flow_r->step()->where('id', '>', $row->step_id)->select(); | ||
159 | + if ($this->request->isPost()) { | ||
160 | + $type = $this->request->post("type"); | ||
161 | + $next_admin_id = $this->request->post("next_admin_id"); | ||
162 | + $log_data = array(); | ||
163 | + $log_data['flow_id'] = $row->flow_id; | ||
164 | + $log_data['types'] = $types; | ||
165 | + $log_data['types_id'] = $row->id; | ||
166 | + $log_data['admin_id'] = $this->auth->id; | ||
167 | + $log_data['nickname'] = $this->auth->nickname; | ||
168 | + $log_data['remark'] = $this->request->post("remark", ''); | ||
169 | + $log_data['is_end'] = 0; | ||
170 | + $log_data['status'] = 0;//未通过 | ||
171 | + Db::startTrans(); | ||
172 | + try { | ||
173 | + //驳回 | ||
174 | + if ($type == 'reject') { | ||
175 | + $row->check_status = 3; | ||
176 | + $row->check_admin_id = "";//已审批的人清空 | ||
177 | + } else { | ||
178 | + //通过 | ||
179 | + //判断是否还有下一级审批人 | ||
180 | + if ($flow_r->config == 1 && $flow_r->step) { | ||
181 | + $flow_admin_id = $flow_r->step[0]['admin_ids']; | ||
182 | + if ($flow_r->step[0]['type'] == 1) { | ||
183 | + //上级领导审批 | ||
184 | + $parentIds = $this->auth->getParentAdminIds($this->auth->id); | ||
185 | + $flow_admin_id = $parentIds ? join(',', $parentIds) : $this->auth->id;//如果没有父类就是最高级的,同时也要审核一下 | ||
186 | + }else if ($flow_r->step[0]['type']==3){ | ||
187 | + //指定部门 | ||
188 | + $auth=new \addons\facrm\library\Auth(); | ||
189 | + $groupIds=$auth->getGroupsAdminIds($flow_r->step[0]['admin_ids']); | ||
190 | + $flow_admin_id=$groupIds?join(',',$groupIds):$this->auth->id;//如部门人自己也要审核一下 | ||
191 | + | ||
192 | + } | ||
193 | + $row->check_status = 1; | ||
194 | + $row->flow_admin_id = $flow_admin_id; | ||
195 | + $row->step_id = $flow_r->step[0]['id']; | ||
196 | + } elseif ($flow_r->config == 0 && $next_admin_id) { | ||
197 | + $row->check_status = 1; | ||
198 | + $row->flow_admin_id = $next_admin_id; | ||
199 | + } else { | ||
200 | + $row->flow_admin_id = ""; | ||
201 | + $row->check_status = 2; | ||
202 | + $log_data['is_end'] = 1; | ||
203 | + } | ||
204 | + $row->check_admin_id .= $row->check_admin_id ? ',' . $this->auth->id : $this->auth->id; | ||
205 | + $log_data['status'] = 1;//通过 | ||
206 | + } | ||
207 | + $row->save(); | ||
208 | + //记录审核日志 | ||
209 | + $Log->save($log_data); | ||
210 | + hook("facrm_flow_verify", array_merge($log_data, ['id' => $Log->id, 'flow' => $flow_r])); | ||
211 | + Db::commit(); | ||
212 | + } catch (Exception $e) { | ||
213 | + Db::rollback(); | ||
214 | + $this->error($e->getMessage()); | ||
215 | + } | ||
216 | + $this->success(); | ||
217 | + } | ||
218 | + $return_data=array(); | ||
219 | + //获取审核日志 | ||
220 | + $log_list = $Log->where('flow_id', $row->flow_id)->where('types_id', $row->id)->select(); | ||
221 | + $return_data['row']=$row; | ||
222 | + $return_data['flow']=$flow_r; | ||
223 | + $return_data['log_list']=$log_list; | ||
224 | + | ||
225 | + switch ($types) { | ||
226 | + case "contract": | ||
227 | + $row->product; | ||
228 | + break; | ||
229 | + } | ||
230 | + $this->success('',$return_data); | ||
231 | + } | ||
232 | + | ||
233 | +} |
addons/facrm/controller/facrm/Common.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller\facrm; | ||
4 | + | ||
5 | +use addons\facrm\library\BackendApi; | ||
6 | +use think\Config; | ||
7 | +use think\Db; | ||
8 | +use think\Exception; | ||
9 | +use think\Hook; | ||
10 | +use think\Request; | ||
11 | + | ||
12 | +use app\common\exception\UploadException; | ||
13 | +use app\common\library\Upload; | ||
14 | +use think\Session; | ||
15 | + | ||
16 | + | ||
17 | +/** | ||
18 | + * 共有无需权限接口 | ||
19 | + * @internal | ||
20 | + */ | ||
21 | +class Common extends BackendApi | ||
22 | +{ | ||
23 | + protected $noNeedRight = ['*']; | ||
24 | + protected $noNeedLogin = ['init','getNoticeTpl']; | ||
25 | + public function _initialize() | ||
26 | + { | ||
27 | + parent::_initialize(); | ||
28 | + //设置过滤方法 | ||
29 | + $this->request->filter(['trim', 'strip_tags', 'htmlspecialchars']); | ||
30 | + } | ||
31 | + | ||
32 | + /** | ||
33 | + * 下拉选择 | ||
34 | + * @ApiParams(name="model", type="string", required=true, description="默认admin") | ||
35 | + * @ApiParams(name="keyField", type="string", required=true, description="主键字段,如id") | ||
36 | + * @ApiParams(name="type", type="string", required=false, description="可以空all代表获取全部") | ||
37 | + */ | ||
38 | + public function selectpage(){ | ||
39 | + | ||
40 | + $modellist=['admin']; | ||
41 | + $model = $this->request->param('model'); | ||
42 | + if (!$this->request->request('keyField')){ | ||
43 | + $this->error("访问出错"); | ||
44 | + } | ||
45 | + if (!in_array($model,$modellist)) | ||
46 | + $this->error("非法访问"); | ||
47 | + | ||
48 | + $this->model = model('\app\admin\model\\'.$model); | ||
49 | + $type = $this->request->param('type'); | ||
50 | + | ||
51 | + | ||
52 | + switch ($model){ | ||
53 | + case 'admin': | ||
54 | + $this->selectpageFields =['id','concat(nickname,"(",id,")") as nickname']; | ||
55 | + $custom=['status'=>'normal']; | ||
56 | + if ($type != "all") { | ||
57 | + $childrenAdminIds = $this->auth->getChildrenAdminIds(true); | ||
58 | + $custom['id']= ['in', $childrenAdminIds]; | ||
59 | + } | ||
60 | + //暂时处理授权审批 检索员工出错问题 | ||
61 | + if (!$this->request->request('searchField')){ | ||
62 | + $this->request->request(['searchField' => 'nickname']); | ||
63 | + } | ||
64 | + $this->request->request(['custom' => $custom]); | ||
65 | + break; | ||
66 | + } | ||
67 | + return parent::selectpage(); | ||
68 | + | ||
69 | + } | ||
70 | + | ||
71 | + /** | ||
72 | + * 读取省市区数据,联动列表 | ||
73 | + * @ApiMethod (GET) | ||
74 | + * @ApiParams(name="province", type="int", required=true, description="省份ID,可空。空就是获取省份列表不空就是获取城市列表") | ||
75 | + * @ApiParams(name="city", type="int", required=true, description="城市ID,可空,空就是获取城市列表不空就是获取区域列表") | ||
76 | + */ | ||
77 | + public function area() | ||
78 | + { | ||
79 | + $params = $this->request->get("row/a"); | ||
80 | + if (!empty($params)) { | ||
81 | + $province = isset($params['province']) ? $params['province'] : ''; | ||
82 | + $city = isset($params['city']) ? $params['city'] : ''; | ||
83 | + } else { | ||
84 | + $province = $this->request->get('province', ''); | ||
85 | + $city = $this->request->get('city', ''); | ||
86 | + } | ||
87 | + $where = ['pid' => 0, 'level' => 1]; | ||
88 | + $provincelist = null; | ||
89 | + if ($province !== '') { | ||
90 | + $where['pid'] = $province; | ||
91 | + $where['level'] = 2; | ||
92 | + if ($city !== '') { | ||
93 | + $where['pid'] = $city; | ||
94 | + $where['level'] = 3; | ||
95 | + } | ||
96 | + } | ||
97 | + $provincelist = Db::name('area')->where($where)->field('id as value,name')->select(); | ||
98 | + $this->success('', $provincelist); | ||
99 | + } | ||
100 | + | ||
101 | + /** | ||
102 | + * 读取所有省市区数据(用于uview select) | ||
103 | + */ | ||
104 | + public function getAllArea(){ | ||
105 | + $lists= \addons\facrm\model\Area::getAllCacheChildren(); | ||
106 | + $this->success('',array_values($lists)); | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * [客户等级、行业类型、来源等] | ||
111 | + */ | ||
112 | + public function baseConfig(){ | ||
113 | + $this->addon_config = get_addon_config('facrm'); | ||
114 | + $this->success('', [ | ||
115 | + 'levelList'=>$this->addon_config['level'], | ||
116 | + 'industryList'=>$this->addon_config['industry'], | ||
117 | + 'sourceList'=>$this->addon_config['source'], | ||
118 | + 'accountList'=>$this->addon_config['account'], | ||
119 | + 'recordTypeList'=>$this->addon_config['record_type'], | ||
120 | + 'cprefix'=>$this->addon_config['cprefix'],//合同编号规则 | ||
121 | + 'rprefix'=>$this->addon_config['rprefix'],//回款编号规则 | ||
122 | + 'deal'=>$this->addon_config['deal'],//开启成交(无需走合同流程) | ||
123 | + ] | ||
124 | + ); | ||
125 | + } | ||
126 | + | ||
127 | + /** | ||
128 | + * 基础配置 | ||
129 | + * @ApiParams (name="preview", type="int", required=false, description="只要传递说明是获取装修预览") | ||
130 | + * @ApiReturnParams (name="login_captcha", type="string", required=false, sample="0",description="是否需要登录验证码") | ||
131 | + * @ApiReturnParams (name="app_id", type="string", required=false, sample="",description="微信公众号ID") | ||
132 | + * @ApiReturnParams (name="config.upload", type="array", required=false, sample="",description="上传配置,config.upload.cdnurl是图片地址cdn") | ||
133 | + * @ApiReturnParams (name="themeconfig", type="obj", required=false, sample="",description="主题配色") | ||
134 | + */ | ||
135 | + public function init(){ | ||
136 | + $third=get_addon_config('third'); | ||
137 | + //配置信息 | ||
138 | + $upload = Config::get('upload'); | ||
139 | + | ||
140 | + //如果非服务端中转模式需要修改为中转 | ||
141 | + if ($upload['storage'] != 'local' && isset($upload['uploadmode']) && $upload['uploadmode'] != 'server') { | ||
142 | + //临时修改上传模式为服务端中转 | ||
143 | + set_addon_config($upload['storage'], ["uploadmode" => "server"], false); | ||
144 | + $upload = \app\common\model\Config::upload(); | ||
145 | + // 上传信息配置后 | ||
146 | + Hook::listen("upload_config_init", $upload); | ||
147 | + | ||
148 | + $upload = Config::set('upload', array_merge(Config::get('upload'), $upload)); | ||
149 | + } | ||
150 | + | ||
151 | + $upload['cdnurl'] = $upload['cdnurl'] ? $upload['cdnurl'] : \request()->domain(); | ||
152 | + $upload['uploadurl'] = preg_match("/^((?:[a-z]+:)?\/\/)(.*)/i", $upload['uploadurl']) ? $upload['uploadurl'] : url($upload['storage'] == 'local' ? '/api/common/upload' : $upload['uploadurl'], '', false, true); | ||
153 | + | ||
154 | + $config = [ | ||
155 | + 'upload' => $upload | ||
156 | + ]; | ||
157 | + $themeconfig=array(); | ||
158 | + if ($this->request->request('preview')){ | ||
159 | + $themeconfig=Session::get("facrmpreviewtheme");//用于预览 | ||
160 | + } | ||
161 | + $themeconfig = $themeconfig?$themeconfig:\addons\facrm\library\Theme::get(); | ||
162 | + | ||
163 | + | ||
164 | + if ($themeconfig){ | ||
165 | + $themeconfig=\addons\facrm\library\Theme::render($themeconfig); | ||
166 | + } | ||
167 | + | ||
168 | + $payConfig=\addons\facrm\library\Order::getPayConfig(); | ||
169 | + | ||
170 | + $this->success('', [ | ||
171 | + 'login_captcha'=>Config::get('fastadmin.login_captcha'),//是否需要验证码, | ||
172 | + 'app_id'=>isset($third['wechat']['app_id'])?$third['wechat']['app_id']:'',//企业微信公众号 | ||
173 | + 'config'=>$config,//上传配置 | ||
174 | + 'themeconfig'=>$themeconfig,//主题设置 | ||
175 | + 'payConfig'=>($payConfig?$payConfig['values']:[]),//在线收款配置 | ||
176 | + ] | ||
177 | + ); | ||
178 | + } | ||
179 | + | ||
180 | + /** | ||
181 | + * 上传文件 | ||
182 | + * @ApiMethod (POST) | ||
183 | + * @param File $file 文件流 | ||
184 | + */ | ||
185 | + public function upload() | ||
186 | + { | ||
187 | + | ||
188 | + $upload_config=config("upload"); | ||
189 | + /** | ||
190 | + * 兼容第三方存储,alioss,其它没有测试。 | ||
191 | + */ | ||
192 | + if ($upload_config['storage']!='local'){ | ||
193 | + | ||
194 | + try { | ||
195 | + Session::set("admin", $this->auth->getAdmin());//兼容需要登录的上传插件 | ||
196 | + request()->module('admin'); | ||
197 | + $objname="\\addons\\".$upload_config["storage"]."\\controller\\Index"; | ||
198 | + $uploadClass=new $objname(); | ||
199 | + | ||
200 | + $upload_config=config("upload"); | ||
201 | + if (isset($upload_config['multipart'])&&$upload_config['multipart']){ | ||
202 | + Request::instance()->post($upload_config['multipart']); | ||
203 | + } | ||
204 | + $uploadClass->upload(); | ||
205 | + | ||
206 | + }catch (Exception $e){ | ||
207 | + $this->error($e->getMessage()); | ||
208 | + } | ||
209 | + } | ||
210 | + | ||
211 | + Config::set('default_return_type', 'json'); | ||
212 | + //必须设定cdnurl为空,否则cdnurl函数计算错误 | ||
213 | + Config::set('upload.cdnurl', ''); | ||
214 | + $chunkid = $this->request->post("chunkid"); | ||
215 | + if ($chunkid) { | ||
216 | + if (!Config::get('upload.chunking')) { | ||
217 | + $this->error(__('Chunk file disabled')); | ||
218 | + } | ||
219 | + $action = $this->request->post("action"); | ||
220 | + $chunkindex = $this->request->post("chunkindex/d"); | ||
221 | + $chunkcount = $this->request->post("chunkcount/d"); | ||
222 | + $filename = $this->request->post("filename"); | ||
223 | + $method = $this->request->method(true); | ||
224 | + if ($action == 'merge') { | ||
225 | + $attachment = null; | ||
226 | + //合并分片文件 | ||
227 | + try { | ||
228 | + $upload = new Upload(); | ||
229 | + $attachment = $upload->merge($chunkid, $chunkcount, $filename); | ||
230 | + } catch (UploadException $e) { | ||
231 | + $this->error($e->getMessage()); | ||
232 | + } | ||
233 | + $this->success(__('上传成功'), ['url' => $attachment->url, 'fullurl' => cdnurl($attachment->url, true)]); | ||
234 | + } elseif ($method == 'clean') { | ||
235 | + //删除冗余的分片文件 | ||
236 | + try { | ||
237 | + $upload = new Upload(); | ||
238 | + $upload->clean($chunkid); | ||
239 | + } catch (UploadException $e) { | ||
240 | + $this->error($e->getMessage()); | ||
241 | + } | ||
242 | + $this->success(); | ||
243 | + } else { | ||
244 | + //上传分片文件 | ||
245 | + //默认普通上传文件 | ||
246 | + $file = $this->request->file('file'); | ||
247 | + try { | ||
248 | + $upload = new Upload($file); | ||
249 | + $upload->chunk($chunkid, $chunkindex, $chunkcount); | ||
250 | + } catch (UploadException $e) { | ||
251 | + $this->error($e->getMessage()); | ||
252 | + } | ||
253 | + $this->success(); | ||
254 | + } | ||
255 | + } else { | ||
256 | + $attachment = null; | ||
257 | + //默认普通上传文件 | ||
258 | + $file = $this->request->file('file'); | ||
259 | + try { | ||
260 | + $upload = new Upload($file); | ||
261 | + $attachment = $upload->upload(); | ||
262 | + } catch (UploadException $e) { | ||
263 | + $this->error($e->getMessage()); | ||
264 | + } | ||
265 | + | ||
266 | + $this->success(__('上传成功'), ['url' => $attachment->url, 'fullurl' => cdnurl($attachment->url, true)]); | ||
267 | + } | ||
268 | + | ||
269 | + } | ||
270 | + | ||
271 | + /** | ||
272 | + * 获取通知模板 | ||
273 | + * @ApiParams (name="type", type="string", required=false, sample="0",description="flow_contract,flow_invoice,clues_customer,flow_receivables,flow_business") | ||
274 | + */ | ||
275 | + public function getNoticeTpl(){ | ||
276 | + $engine = $this->request->request('engine','Min'); | ||
277 | + $type = $this->request->request('type','');//flow_contract ,flow_receivables,clues_customer,flow_business | ||
278 | + | ||
279 | + //由于微信订阅通知最多只能有3条订阅 所以专门做了此修改 | ||
280 | + //审批合同相关通知, | ||
281 | + $flow_contract=['notice_flow_contract','notice_pass_contract','notice_nopass_contract']; | ||
282 | + //审批回款通知 | ||
283 | + $flow_receivables=['notice_pass_receivables','notice_flow_receivables','notice_nopass_receivables']; | ||
284 | + //线索和客户 | ||
285 | + $clues_customer=['notice_flow_customer','notice_expire_ccustomer','notice_flow_clues']; | ||
286 | + //商机 | ||
287 | + $flow_business=['notice_flow_business']; | ||
288 | + //发票 | ||
289 | + $flow_invoice=['notice_flow_invoice_nopass','notice_invoice_opener']; | ||
290 | + | ||
291 | + | ||
292 | + $data_temp = \addons\facrm\library\notice\Notice::getTempLplData(); | ||
293 | + $keys=array(); | ||
294 | + foreach ( $data_temp as $row){ | ||
295 | + if(isset($$type)&&in_array($row['key'],$$type)){ | ||
296 | + $keys[]=$row['key'].$engine; | ||
297 | + } | ||
298 | + } | ||
299 | + $lists=\app\admin\model\facrm\Setting::where('key','in',$keys)->where('status',1)->select(); | ||
300 | + $this->success('',$lists); | ||
301 | + } | ||
302 | + | ||
303 | + /** | ||
304 | + * 检查权限 | ||
305 | + */ | ||
306 | + public function authcheck(){ | ||
307 | + $auth = $this->request->post('auth'); | ||
308 | + $this->success('',($auth&&$this->auth->check($auth))?1:0); | ||
309 | + } | ||
310 | + | ||
311 | + /** | ||
312 | + * 腾讯地图经纬度返回地址 | ||
313 | + * @ApiParams (name="lat", type="string", required=true, description="lat<纬度>,lng<经度>") | ||
314 | + * @ApiParams (name="lng", type="string", required=true, description="lat<纬度>,lng<经度>") | ||
315 | + * @ApiReturnParams (name="address", type="string", required=true, sample="0",description="定位地址") | ||
316 | + */ | ||
317 | + public function geocoder(){ | ||
318 | + $url="https://apis.map.qq.com/ws/geocoder/v1/"; | ||
319 | + $addon_config = get_addon_config('facrm'); | ||
320 | + | ||
321 | + if (!isset($addon_config['map_qq_key'])||!$addon_config['map_qq_key']){ | ||
322 | + $this->error('腾讯地图KEY未配置'); | ||
323 | + } | ||
324 | + | ||
325 | + | ||
326 | + //lat<纬度>,lng<经度> | ||
327 | + $lat=$this->request->get('lat'); | ||
328 | + $lng=$this->request->get('lng'); | ||
329 | + //location= 39.984154,116.307490 | ||
330 | + if (!$lat||!$lng){ | ||
331 | + $this->error("经纬度有误"); | ||
332 | + } | ||
333 | + | ||
334 | + $params=['location'=>"{$lat},{$lng}",'key'=>$addon_config['map_qq_key']]; | ||
335 | + | ||
336 | + $cachekey=md5("{$lat},{$lng}"); | ||
337 | + $result=cache($cachekey); | ||
338 | + if (!$result){ | ||
339 | + //缓存没有才去接口那里获取 | ||
340 | + $result=\fast\Http::get($url,$params); | ||
341 | + $result=json_decode($result,true); | ||
342 | + if (!$result||!isset($result['status'])||$result['status']!=0||!isset($result['result']['address'])){ | ||
343 | + $this->error('获取地址错误'); | ||
344 | + } | ||
345 | + cache($cachekey,$result,86400*30); | ||
346 | + } | ||
347 | + | ||
348 | + $this->success('',['address'=>$result['result']['address']]); | ||
349 | + } | ||
350 | + | ||
351 | + | ||
352 | +} |
addons/facrm/controller/facrm/Dashboard.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller\facrm; | ||
4 | + | ||
5 | +use addons\facrm\library\BackendApi; | ||
6 | +use app\admin\model\AuthGroup; | ||
7 | +use app\admin\model\facrm\Contract; | ||
8 | +use app\admin\model\facrm\contract\Receivables; | ||
9 | +use addons\facrm\model\Admin as AdminModel; | ||
10 | +use fast\Tree; | ||
11 | + | ||
12 | +/** | ||
13 | + * 首页 | ||
14 | + * @icon fa fa-dashboard | ||
15 | + * @remark 用于展示当前系统中的统计数据、统计报表及重要实时数据 | ||
16 | + */ | ||
17 | +class Dashboard extends BackendApi | ||
18 | +{ | ||
19 | + | ||
20 | + protected $groupList = []; | ||
21 | + protected $groupdata = []; | ||
22 | + protected $noNeedRight = ['getAchievement','getNotice']; | ||
23 | + | ||
24 | + public function _initialize() | ||
25 | + { | ||
26 | + parent::_initialize(); | ||
27 | + $this->model = new AdminModel(); | ||
28 | + $this->childrenAdminIds = $this->auth->getChildrenAdminIds(true); | ||
29 | + $this->childrenGroupIds = $this->auth->getChildrenGroupIds(true); | ||
30 | + | ||
31 | + $this->groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray(); | ||
32 | + Tree::instance()->init($this->groupList); | ||
33 | + if ($this->auth->isSuperAdmin()) { | ||
34 | + $result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0)); | ||
35 | + foreach ($result as $k => $v) { | ||
36 | + $this->groupdata[$v['id']] = $v['name']; | ||
37 | + } | ||
38 | + } else { | ||
39 | + $result = []; | ||
40 | + $groups = $this->auth->getGroups(); | ||
41 | + foreach ($groups as $m => $n) { | ||
42 | + $childlist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['id'])); | ||
43 | + $temp = []; | ||
44 | + foreach ($childlist as $k => $v) { | ||
45 | + $temp[$v['id']] = $v['name']; | ||
46 | + } | ||
47 | + $result[__($n['name'])] = $temp; | ||
48 | + } | ||
49 | + $this->groupdata = $result; | ||
50 | + } | ||
51 | + } | ||
52 | + | ||
53 | + /** | ||
54 | + * 首页数据 | ||
55 | + * @ApiMethod (POST|GET) | ||
56 | + * @ApiParams(name="type", type="string", required=true, description="oneself:自己,team团队") | ||
57 | + * @ApiReturnParams (name="communicate", type="int", required=false, sample="0",description="待跟进客户") | ||
58 | + * @ApiReturnParams (name="lose_num", type="int", required=false, sample="0",description="将过期客户") | ||
59 | + * @ApiReturnParams (name="business", type="int", required=false, sample="0",description="待跟进商机") | ||
60 | + * @ApiReturnParams (name="contract_expire", type="int", required=false, sample="0",description="过期合同") | ||
61 | + * @ApiReturnParams (name="contract_return", type="int", required=false, sample="0",description="待回款合同") | ||
62 | + * @ApiReturnParams (name="contract_flow", type="int", required=false, sample="0",description="待审核合同") | ||
63 | + * @ApiReturnParams (name="receivables_flow", type="int", required=false, sample="0",description="待审核回款") | ||
64 | + * @ApiReturnParams (name="clues_num", type="int", required=false, sample="0",description="待跟进线索") | ||
65 | + */ | ||
66 | + public function index() | ||
67 | + { | ||
68 | + $year = $this->request->param('year', date("Y", time()), 'intval'); | ||
69 | + $month = $this->request->param('month', intval(date("m", time())), 'intval'); | ||
70 | + $config = $this->request->param('config', 1, 'intval');//$config 1=>'合同金额',2=>'回款金额' | ||
71 | + $group_id = $this->request->param('group_id', 0, 'intval');//部门 | ||
72 | + $admin_id = $this->request->param('admin_id', 0, 'intval');//员工 | ||
73 | + $type = $this->request->param('type', 'oneself'); | ||
74 | + $achievementModel = new \app\admin\model\facrm\Achievement(); | ||
75 | + | ||
76 | + | ||
77 | + //当天开始时间 | ||
78 | + $start_time = strtotime(date("Y-m-d", time())); | ||
79 | + //当天结束之间 | ||
80 | + $end_time = $start_time + 60 * 60 * 24; | ||
81 | + | ||
82 | + switch ($type) { | ||
83 | + case 'oneself': | ||
84 | + $return_data=$this->getNotice(true); | ||
85 | + if (!$achievement = $achievementModel->achievement($config, $year, $month, 3, $this->auth->id, $this->auth->id)) { | ||
86 | + $this->error($achievementModel->getError()); | ||
87 | + } | ||
88 | + $return_data['achievement'] = $achievement; | ||
89 | + //自己的end | ||
90 | + break; | ||
91 | + case 'team': | ||
92 | + $return_data=$this->getNotice(true); | ||
93 | + if ($group_id && !$admin_id) { | ||
94 | + //如果有选团队并且没有选员工就是团队业绩 | ||
95 | + Tree::instance()->init($this->groupList); | ||
96 | + $this->childrenGroupIds = Tree::instance()->getChildrenIds($group_id, true); | ||
97 | + | ||
98 | + $authGroupList = \app\admin\model\AuthGroupAccess:: | ||
99 | + field('uid,group_id') | ||
100 | + ->where('group_id', 'in', $this->childrenGroupIds) | ||
101 | + ->select(); | ||
102 | + $this->childrenAdminIds=[]; | ||
103 | + foreach ($authGroupList as $k => $v) { | ||
104 | + if ($this->childrenAdminIds && in_array($v['uid'], $this->childrenAdminIds)) continue; | ||
105 | + $this->childrenAdminIds[] = $v['uid']; | ||
106 | + } | ||
107 | + | ||
108 | + } else if($admin_id) { | ||
109 | + $this->childrenAdminIds = $admin_id ; | ||
110 | + $this->childrenGroupIds=$admin_id; | ||
111 | + } | ||
112 | + | ||
113 | + $team_achievement = $achievementModel->achievement($config, $year, $month, 2, $this->childrenGroupIds, $this->childrenAdminIds); | ||
114 | + $team_achievement['config']=$config; | ||
115 | + $return_data =array_merge($return_data, | ||
116 | + [ | ||
117 | + 'achievement' => $team_achievement, | ||
118 | + ]) ; | ||
119 | + break; | ||
120 | + //团队的end | ||
121 | + default: | ||
122 | + $this->error(__("访问有误")); | ||
123 | + } | ||
124 | + | ||
125 | + $this->success('', $return_data); | ||
126 | + | ||
127 | + | ||
128 | + } | ||
129 | + | ||
130 | + /** | ||
131 | + * 消息和提醒 | ||
132 | + * @ApiParams(name="type", type="string", required=true, description="oneself:自己,team团队") | ||
133 | + * @ApiReturnParams (name="communicate", type="int", required=false, sample="0",description="待跟进客户") | ||
134 | + * @ApiReturnParams (name="lose_num", type="int", required=false, sample="0",description="将过期客户") | ||
135 | + * @ApiReturnParams (name="business", type="int", required=false, sample="0",description="待跟进商机") | ||
136 | + * @ApiReturnParams (name="contract_expire", type="int", required=false, sample="0",description="过期合同") | ||
137 | + * @ApiReturnParams (name="contract_return", type="int", required=false, sample="0",description="待回款合同") | ||
138 | + * @ApiReturnParams (name="contract_flow", type="int", required=false, sample="0",description="待审核合同") | ||
139 | + * @ApiReturnParams (name="receivables_flow", type="int", required=false, sample="0",description="待审核回款") | ||
140 | + * @ApiReturnParams (name="clues_num", type="int", required=false, sample="0",description="待跟进线索") | ||
141 | + * @ApiReturnParams (name="invoice_flow", type="int", required=false, sample="0",description="待审批发票") | ||
142 | + * @ApiReturnParams (name="invoice_opener", type="int", required=false, sample="0",description="待开具发票") | ||
143 | + */ | ||
144 | + public function getNotice($isReturn=false){ | ||
145 | + $type = $this->request->param('type', 'oneself'); | ||
146 | + $businessModel = model('\app\admin\model\facrm\Business'); | ||
147 | + $customerModel = model('\app\admin\model\facrm\Customer'); | ||
148 | + $cluesModel = model('\app\admin\model\facrm\Clues'); | ||
149 | + $contractModel = model('\app\admin\model\facrm\Contract'); | ||
150 | + $receivablesModel = model('\app\admin\model\facrm\contract\Receivables'); | ||
151 | + $invoiceModel = model('\app\admin\model\facrm\Invoice'); | ||
152 | + //当天开始时间 | ||
153 | + $start_time = strtotime(date("Y-m-d", time())); | ||
154 | + //当天结束之间 | ||
155 | + $end_time = $start_time + 60 * 60 * 24; | ||
156 | + | ||
157 | + //更新到期回款计划 | ||
158 | + $planModel =new \app\admin\model\facrm\contract\Plan(); | ||
159 | + $planModel->where('plan_time', '<', time())->where('status',0)->update(['status'=>'-1']); | ||
160 | + $plan=0; | ||
161 | + if ($this->auth->check('facrm/contract/plan/index')){ | ||
162 | + $time=time(); | ||
163 | + $planModel->with(['contract']); | ||
164 | + if (!$this->auth->isSuperAdmin() && !$this->auth->check('facrm/contract/index/index')) { | ||
165 | + $planModel->where('contract.order_admin_id', 'in', $this->auth->getChildrenAdminIds(true)); | ||
166 | + } | ||
167 | + $plan=$planModel->where('plan_time','<',\think\Db::raw(" ({$time}+(`remind_day`*86400))"))->where('status','neq',2) | ||
168 | + ->fetchSql(false)->count(); | ||
169 | + } | ||
170 | + | ||
171 | + switch ($type) { | ||
172 | + case 'oneself': | ||
173 | + //自己的start | ||
174 | + $this->childrenAdminIds = $this->auth->getChildrenAdminIds(true); | ||
175 | + $filter_w['owner_user_id'] = $this->auth->id; | ||
176 | + | ||
177 | + //需要联系客户 | ||
178 | + $communicate = $customerModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count(); | ||
179 | + | ||
180 | + //待跟进线索 | ||
181 | + $clues_num = $cluesModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count(); | ||
182 | + | ||
183 | + //将要过期的客户 | ||
184 | + $lose_num = count($customerModel->getLose($this->auth->id)); | ||
185 | + | ||
186 | + $business = $businessModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count(); | ||
187 | + //是否有合同权限 | ||
188 | + $contract_return = $contract_expire = 0; | ||
189 | + if ($this->auth->check('facrm/contract/index')) { | ||
190 | + $filter_w['check_status'] = 2; | ||
191 | + //快过期和过期合同 | ||
192 | + $contract_expire = $contractModel->where('end_time', 'between', [1, $end_time + (30 * 86400)])->where('expire_handle', 0)->where($filter_w)->count(); | ||
193 | + //待回款合同 | ||
194 | + $contract_return = $contractModel->where("money", "exp", ">return_money")->where($filter_w)->count(); | ||
195 | + } | ||
196 | + //合同审核和回款审核 | ||
197 | + $contract_flow = $contractModel->where('find_in_set(:id,flow_admin_id)', ['id' => $this->auth->id])->where('check_status', 'in', [0, 1])->count(); | ||
198 | + $receivables_flow = $receivablesModel->where('find_in_set(:id,flow_admin_id)', ['id' => $this->auth->id])->where('check_status', 'in', [0, 1])->count(); | ||
199 | + | ||
200 | + //待审发票 | ||
201 | + $invoice_flow=$invoiceModel->where('find_in_set(:id,flow_admin_id)', ['id' => $this->auth->id])->where('check_status', 'in', [0, 1])->count(); | ||
202 | + //待开具发票 | ||
203 | + $invoice_opener=$invoiceModel->where('status', 'in', [0, 1])->where('check_status', 2)->count(); | ||
204 | + | ||
205 | + | ||
206 | + | ||
207 | + | ||
208 | + | ||
209 | + $return_data = [ | ||
210 | + 'communicate' => $communicate,//待跟进客户 | ||
211 | + 'lose_num' => $lose_num, //将过期客户 | ||
212 | + 'business' => $business,//待跟进商机 | ||
213 | + 'contract_expire' => $contract_expire,//过期合同 | ||
214 | + 'contract_return' => $contract_return,//待回款合同 | ||
215 | + 'contract_flow' => $contract_flow,//待合同审核 | ||
216 | + 'receivables_flow' => $receivables_flow,//待回款审核 | ||
217 | + 'clues_num'=>$clues_num,//待跟进线索 | ||
218 | + 'invoice_flow'=> $invoice_flow, | ||
219 | + 'invoice_opener'=>$invoice_opener, | ||
220 | + 'plan'=>$plan | ||
221 | + | ||
222 | + ]; | ||
223 | + //自己的end | ||
224 | + break; | ||
225 | + case 'team': | ||
226 | + $this->childrenAdminIds = $this->auth->getChildrenAdminIds(true); | ||
227 | + //团队的 | ||
228 | + $filter_w = array(); | ||
229 | + $filter_w['owner_user_id'] = ['in', $this->childrenAdminIds]; | ||
230 | + //需要联系客户 | ||
231 | + $team_communicate = $customerModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count(); | ||
232 | + | ||
233 | + //待跟进线索 | ||
234 | + $clues_num = $cluesModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count(); | ||
235 | + | ||
236 | + //将要过期的用户 | ||
237 | + $team_lose_num = count($customerModel->getLose($this->childrenAdminIds)); | ||
238 | + | ||
239 | + $team_business = $businessModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count(); | ||
240 | + //是否有合同权限 | ||
241 | + $team_contract_return = $team_contract_expire = 0; | ||
242 | + if ($this->auth->check('facrm/contract/index')) { | ||
243 | + $filter_w['check_status'] = 2; | ||
244 | + //快过期和过期合同 | ||
245 | + $team_contract_expire = $contractModel->where('end_time', 'between', [1, $end_time + (30 * 86400)])->where('expire_handle', 0)->where($filter_w)->count(); | ||
246 | + //待回款合同 | ||
247 | + $team_contract_return = $contractModel->where("money", "exp", ">return_money")->where($filter_w)->count(); | ||
248 | + } | ||
249 | + | ||
250 | + $return_data = [ | ||
251 | + 'communicate' => $team_communicate, | ||
252 | + 'lose_num' => $team_lose_num, | ||
253 | + 'clues_num'=>$clues_num,//待跟进线索 | ||
254 | + 'business' => $team_business, | ||
255 | + 'contract_expire' => $team_contract_expire, | ||
256 | + 'contract_return' => $team_contract_return, | ||
257 | + 'plan'=>$plan | ||
258 | + ]; | ||
259 | + break; | ||
260 | + //团队的end | ||
261 | + default: | ||
262 | + $this->error(__("访问有误")); | ||
263 | + } | ||
264 | + if ($isReturn){ | ||
265 | + return $return_data; | ||
266 | + } | ||
267 | + | ||
268 | + $this->success('', $return_data); | ||
269 | + | ||
270 | + } | ||
271 | + | ||
272 | + | ||
273 | + | ||
274 | +} |
addons/facrm/controller/facrm/Fields.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller\facrm; | ||
4 | + | ||
5 | +use addons\facrm\library\BackendApi; | ||
6 | +use app\common\model\Config; | ||
7 | +use fast\Tree; | ||
8 | +use think\Db; | ||
9 | + | ||
10 | +/** | ||
11 | + * 自定义字段 | ||
12 | + * | ||
13 | + * @icon fa fa-circle-o | ||
14 | + */ | ||
15 | +class Fields extends BackendApi | ||
16 | +{ | ||
17 | + | ||
18 | + /** | ||
19 | + * Fields模型对象 | ||
20 | + */ | ||
21 | + protected $model = null; | ||
22 | + protected $modelValidate = true; | ||
23 | + protected $modelSceneValidate = true; | ||
24 | + protected $noNeedRight = ['get_fields','selectpage']; | ||
25 | + private $modelList = array(); | ||
26 | + | ||
27 | + public function _initialize() | ||
28 | + { | ||
29 | + parent::_initialize(); | ||
30 | + $this->model = new \app\admin\model\facrm\Fields; | ||
31 | + $this->modelList = [ | ||
32 | + 'customer' => __('客户'), | ||
33 | + 'customer_contacts' => __('联系人'), | ||
34 | + 'contract'=>__("合同"), | ||
35 | + 'contract_receivables'=>__("回款"), | ||
36 | + 'business'=>__("商机"), | ||
37 | + 'clues'=>__("线索"), | ||
38 | + ]; | ||
39 | + $this->request->filter(['strip_tags']); | ||
40 | + } | ||
41 | + /** | ||
42 | + * 获取自定义字段 | ||
43 | + * @ApiParams(name="source", type="string", required=true, description="customer:客户,customer_contacts联系人") | ||
44 | + * @ApiParams(name="id", type="int", required=true, description="对应数据的id") | ||
45 | + */ | ||
46 | + public function get_fields() | ||
47 | + { | ||
48 | + $source=$this->request->request('source',''); | ||
49 | + | ||
50 | + if (!in_array($source, array_keys($this->modelList))) { | ||
51 | + $this->error(__("未开放信息")); | ||
52 | + } | ||
53 | + $source=ucfirst($source); | ||
54 | + | ||
55 | + $id = $this->request->param('id', 0, 'intval'); | ||
56 | + switch ($source) { | ||
57 | + case 'Contract_receivables': | ||
58 | + $this->model = model('\app\admin\model\facrm\contract\Receivables'); | ||
59 | + break; | ||
60 | + case 'Customer_contacts': | ||
61 | + $this->model = model('\app\admin\model\facrm\customer\Contacts'); | ||
62 | + break; | ||
63 | + default: | ||
64 | + $this->model = model("\\app\\admin\\model\\facrm\\{$source}"); | ||
65 | + } | ||
66 | + | ||
67 | + $values = []; | ||
68 | + if ($id > 0) { | ||
69 | + $values = $this->model->find($id); | ||
70 | + } | ||
71 | + $fields = \app\admin\model\facrm\Fields::getCustomFields($source, $values); | ||
72 | + if ($values&&$fields){ | ||
73 | + foreach ($fields as &$row){ | ||
74 | + if (isset($values[$row['name']]))$row['value']=$values[$row['name']]; | ||
75 | + } | ||
76 | + } | ||
77 | + | ||
78 | + $this->success('',array('fields'=> $fields)); | ||
79 | + | ||
80 | + } | ||
81 | + | ||
82 | + /** | ||
83 | + * 关联表联动 | ||
84 | + * @internal | ||
85 | + */ | ||
86 | + public function selectpage() | ||
87 | + { | ||
88 | + $id = $this->request->get("id/d", 0); | ||
89 | + $fieldInfo = $this->model::get($id); | ||
90 | + if (!$fieldInfo) { | ||
91 | + $this->error("未找到指定字段"); | ||
92 | + } | ||
93 | + $setting = $fieldInfo['setting']; | ||
94 | + if (!$setting || !isset($setting['table'])) { | ||
95 | + $this->error("字段配置不正确"); | ||
96 | + } | ||
97 | + //搜索关键词,客户端输入以空格分开,这里接收为数组 | ||
98 | + $word = (array)$this->request->request("q_word/a"); | ||
99 | + //当前页 | ||
100 | + $page = $this->request->request("pageNumber"); | ||
101 | + //分页大小 | ||
102 | + $pagesize = $this->request->request("pageSize"); | ||
103 | + //搜索条件 | ||
104 | + $andor = $this->request->request("andOr", "and", "strtoupper"); | ||
105 | + //排序方式 | ||
106 | + $orderby = (array)$this->request->request("orderBy/a"); | ||
107 | + //显示的字段 | ||
108 | + //$field = $this->request->request("showField"); | ||
109 | + $field = $setting['field']; | ||
110 | + //主键 | ||
111 | + //$primarykey = $this->request->request("keyField"); | ||
112 | + $primarykey = $setting['primarykey']; | ||
113 | + //主键值 | ||
114 | + $primaryvalue = $this->request->request("keyValue"); | ||
115 | + //搜索字段 | ||
116 | + $searchfield = (array)$this->request->request("searchField/a"); | ||
117 | + $searchfield = [$field, $primarykey]; | ||
118 | + //自定义搜索条件 | ||
119 | + $custom = (array)$this->request->request("custom/a"); | ||
120 | + $custom = isset($setting['conditions']) ? (array)json_decode($setting['conditions'], true) : []; | ||
121 | + $custom = array_filter($custom); | ||
122 | + | ||
123 | + $admin_id = session('admin.id') ?: 0; | ||
124 | + $user_id = $this->auth->id ?: 0; | ||
125 | + //如果是管理员需要移除user_id筛选,否则会导致管理员无法筛选列表信息 | ||
126 | + $admin = $this->request->request("admin/d"); | ||
127 | + if ($admin_id && $admin) { | ||
128 | + unset($custom['user_id']); | ||
129 | + } else { | ||
130 | + //如果不是管理员则需要判断是否开放相应的投稿字段 | ||
131 | + if (!in_array($fieldInfo['source'], array_keys($this->modelList))) { | ||
132 | + $this->error("未开放栏目信息"); | ||
133 | + } | ||
134 | + } | ||
135 | + | ||
136 | + //是否返回树形结构 | ||
137 | + $istree = $this->request->request("isTree", 0); | ||
138 | + $ishtml = $this->request->request("isHtml", 0); | ||
139 | + if ($istree) { | ||
140 | + $word = []; | ||
141 | + $pagesize = 99999; | ||
142 | + } | ||
143 | + $order = []; | ||
144 | + foreach ($orderby as $k => $v) { | ||
145 | + $order[$v[0]] = $v[1]; | ||
146 | + } | ||
147 | + $field = $field ? $field : 'name'; | ||
148 | + | ||
149 | + //如果有primaryvalue,说明当前是初始化传值 | ||
150 | + if ($primaryvalue !== null) { | ||
151 | + $where = [$primarykey => ['in', $primaryvalue]]; | ||
152 | + $where = function ($query) use ($primaryvalue, $custom, $admin_id, $user_id) { | ||
153 | + $query->where('id', 'in', $primaryvalue); | ||
154 | + if ($custom && is_array($custom)) { | ||
155 | + //替换暂位符 | ||
156 | + $search = ["{admin_id}", "{user_id}"]; | ||
157 | + $replace = [$admin_id, $user_id]; | ||
158 | + foreach ($custom as $k => $v) { | ||
159 | + if (is_array($v) && 2 == count($v)) { | ||
160 | + $query->where($k, trim($v[0]), str_replace($search, $replace, $v[1])); | ||
161 | + } else { | ||
162 | + $query->where($k, '=', str_replace($search, $replace, $v)); | ||
163 | + } | ||
164 | + } | ||
165 | + } | ||
166 | + }; | ||
167 | + $pagesize = 99999; | ||
168 | + } else { | ||
169 | + $where = function ($query) use ($word, $andor, $field, $searchfield, $custom, $admin_id, $user_id) { | ||
170 | + $logic = $andor == 'AND' ? '&' : '|'; | ||
171 | + $searchfield = is_array($searchfield) ? implode($logic, $searchfield) : $searchfield; | ||
172 | + $word = array_filter($word); | ||
173 | + if ($word) { | ||
174 | + foreach ($word as $k => $v) { | ||
175 | + $query->where(str_replace(',', $logic, $searchfield), "like", "%{$v}%"); | ||
176 | + } | ||
177 | + } | ||
178 | + if ($custom && is_array($custom)) { | ||
179 | + //替换暂位符 | ||
180 | + $search = ["{admin_id}", "{user_id}"]; | ||
181 | + $replace = [$admin_id, $user_id]; | ||
182 | + foreach ($custom as $k => $v) { | ||
183 | + if (is_array($v) && 2 == count($v)) { | ||
184 | + $query->where($k, trim($v[0]), str_replace($search, $replace, $v[1])); | ||
185 | + } else { | ||
186 | + $query->where($k, '=', str_replace($search, $replace, $v)); | ||
187 | + } | ||
188 | + } | ||
189 | + } | ||
190 | + }; | ||
191 | + } | ||
192 | + $list = []; | ||
193 | + $total = Db::table($setting['table'])->where($where)->count(); | ||
194 | + if ($total > 0) { | ||
195 | + $datalist = Db::table($setting['table'])->where($where) | ||
196 | + ->order($order) | ||
197 | + ->page($page, $pagesize) | ||
198 | + ->field($primarykey . "," . $field . ($istree ? ",pid" : "")) | ||
199 | + ->select(); | ||
200 | + foreach ($datalist as $index => &$item) { | ||
201 | + unset($item['password'], $item['salt']); | ||
202 | + $list[] = [ | ||
203 | + $primarykey => isset($item[$primarykey]) ? $item[$primarykey] : '', | ||
204 | + $field => isset($item[$field]) ? $item[$field] : '', | ||
205 | + 'pid' => isset($item['pid']) ? $item['pid'] : 0 | ||
206 | + ]; | ||
207 | + } | ||
208 | + if ($istree && !$primaryvalue) { | ||
209 | + $tree = Tree::instance(); | ||
210 | + $tree->init($list, 'pid'); | ||
211 | + $list = $tree->getTreeList($tree->getTreeArray(0), $field); | ||
212 | + if (!$ishtml) { | ||
213 | + foreach ($list as &$item) { | ||
214 | + $item = str_replace(' ', ' ', $item); | ||
215 | + } | ||
216 | + unset($item); | ||
217 | + } | ||
218 | + } | ||
219 | + } | ||
220 | + //这里一定要返回有list这个字段,total是可选的,如果total<=list的数量,则会隐藏分页按钮 | ||
221 | + $this->success('', ['list' => $list, 'total' => $total]); | ||
222 | + } | ||
223 | + | ||
224 | + | ||
225 | + | ||
226 | +} |
addons/facrm/controller/facrm/Invoice.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller\facrm; | ||
4 | + | ||
5 | + | ||
6 | +use addons\facrm\library\BackendApi; | ||
7 | +use think\Db; | ||
8 | +use think\Exception; | ||
9 | +use think\exception\PDOException; | ||
10 | +use think\exception\ValidateException; | ||
11 | + | ||
12 | + | ||
13 | + | ||
14 | +/** | ||
15 | + * 发票管理 | ||
16 | + */ | ||
17 | +class Invoice extends BackendApi | ||
18 | +{ | ||
19 | + | ||
20 | + protected $model = null; | ||
21 | + /** | ||
22 | + * 快速搜索时执行查找的字段 | ||
23 | + */ | ||
24 | + protected $searchFields = 'invoice_name'; | ||
25 | + protected $childrenAdminIds = []; | ||
26 | + protected $noNeedRight = [ 'selectpage','history']; | ||
27 | + protected $tpl_key="invoice_tpl"; | ||
28 | + | ||
29 | + public function _initialize() | ||
30 | + { | ||
31 | + parent::_initialize(); | ||
32 | + $this->model = model('\app\admin\model\facrm\Invoice'); | ||
33 | + //设置过滤方法 | ||
34 | + $this->request->filter(['trim', 'strip_tags', 'htmlspecialchars']); | ||
35 | + } | ||
36 | + | ||
37 | + /** | ||
38 | + * 我申请的发票 | ||
39 | + * @ApiSummary (返回值里面有scene_list,如果有all全部发票就有权限) | ||
40 | + * @ApiMethod (GET) | ||
41 | + * @ApiReturnParams (name="scene_list", type="array", required=true, sample="0") | ||
42 | + * @ApiBody ("filter里面的scene_id是必传的,参考PC[owner我申请的发票,branch下属申请的发票all全部申请的发票]") | ||
43 | + */ | ||
44 | + public function index($scene_list=array()) | ||
45 | + { | ||
46 | + //设置过滤方法 | ||
47 | + $this->request->filter(['strip_tags']); | ||
48 | + $scene_list = $scene_list?$scene_list:['owner'=>'我申','branch'=>'下属']; | ||
49 | + $customer_id = $this->request->param("customer_id"); | ||
50 | + $filter_w = $this->getFilterWhere($scene_list); | ||
51 | + | ||
52 | + if ($customer_id) { | ||
53 | + $filter_w['customer_id'] = $customer_id; | ||
54 | + } | ||
55 | + //如果发送的来源是Selectpage,则转发到Selectpage | ||
56 | + if ($this->request->request('keyField')) { | ||
57 | + $this->request->request(['custom' => $filter_w]); | ||
58 | + return $this->selectpage(); | ||
59 | + } | ||
60 | + | ||
61 | + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); | ||
62 | + $total = $this->model | ||
63 | + ->where($where) | ||
64 | + ->where($filter_w) | ||
65 | + ->with([ | ||
66 | + ]) | ||
67 | + ->order($sort, $order)->fetchSql(false) | ||
68 | + ->count(); | ||
69 | + $list = $this->model | ||
70 | + ->where($where) | ||
71 | + ->where($filter_w) | ||
72 | + ->with([ | ||
73 | + 'createUser' => function ($user) { | ||
74 | + $user->field('id,username,nickname'); | ||
75 | + }, | ||
76 | + 'contract' => function ($user) { | ||
77 | + $user->field('id,name,number'); | ||
78 | + }, | ||
79 | + 'customer' => function ($customer) { | ||
80 | + $customer->field('id,name'); | ||
81 | + }, | ||
82 | + ]) | ||
83 | + ->order($sort, $order) | ||
84 | + ->limit($offset, $limit)->fetchSql(false) | ||
85 | + ->select(); | ||
86 | + $scene_list=['owner'=>'我申发票']; | ||
87 | + | ||
88 | + if ($this->auth->check('facrm/invoice/index/lists')){ | ||
89 | + $scene_list['all']="全部发票"; | ||
90 | + } | ||
91 | + if ($this->auth->check('facrm/invoice/index/opener')){ | ||
92 | + $scene_list['opener']="财务待开"; | ||
93 | + } | ||
94 | + $this->success('',array( "total" => $total,"rows" => $list,'scene_list'=>$scene_list)); | ||
95 | + | ||
96 | + } | ||
97 | + | ||
98 | + | ||
99 | + /** | ||
100 | + * 全部发票 | ||
101 | + * @ApiMethod (GET) | ||
102 | + * @ApiBody ("filter里面的scene_id是必须是all") | ||
103 | + */ | ||
104 | + public function lists(){ | ||
105 | + return $this->index(['all'=>'全部发票']); | ||
106 | + } | ||
107 | + /** | ||
108 | + * 申请 | ||
109 | + * @ApiMethod (GET) | ||
110 | + * @return mixed | ||
111 | + * @ApiBody ("GET获取参数,【flow审核配置,setting发票配置】,POST提交申请,参数参考PC") | ||
112 | + */ | ||
113 | + public function add() | ||
114 | + { | ||
115 | + | ||
116 | + $flow = model('\app\admin\model\facrm\Flow'); | ||
117 | + $flow_r =\app\admin\model\facrm\Flow::getFlow($this->auth->id, 'invoice'); | ||
118 | + | ||
119 | + if (!$flow_r) $this->error(__('审批配置不存在,请先配置')); | ||
120 | + //获取发票配置 | ||
121 | + $settingModel = new \app\admin\model\facrm\Setting(); | ||
122 | + $setting = $settingModel->where('key',$this->tpl_key)->where('status',1)->value('values'); | ||
123 | + if (!$setting){ | ||
124 | + $this->error(__('发票开具申请未开启')); | ||
125 | + } | ||
126 | + | ||
127 | + if ($this->request->isPost()) { | ||
128 | + $params = $this->request->post("row/a"); | ||
129 | + if (!isset($params['contract_id'])) | ||
130 | + $this->error(__('请选择合同')); | ||
131 | + | ||
132 | + | ||
133 | + $contractModel = new \app\admin\model\facrm\Contract(); | ||
134 | + //获取合同情况 | ||
135 | + $contract_r = $contractModel->get($params['contract_id']); | ||
136 | + if (!$contract_r) | ||
137 | + $this->error(__('没有找到合同')); | ||
138 | + | ||
139 | + | ||
140 | + if ($contract_r['check_status']!=2) | ||
141 | + $this->error(__('合同未通过审核不能申请发票')); | ||
142 | + | ||
143 | + | ||
144 | + if ($this->model->where('contract_id',$contract_r['id'])->where(function ($query){ | ||
145 | + $query->where('check_status','in',[0,1])->whereOr('status','in',[0,1]); | ||
146 | + })->count()){ | ||
147 | + $this->error(__("该合同还有未审批或未开票的申请")); | ||
148 | + } | ||
149 | + //判断开票金额,不能大于合同金额且不能大于回款金额 | ||
150 | + $money=bcadd($params['money'],$contract_r['invoice_money'],2); | ||
151 | + | ||
152 | + if ($money>$contract_r['money']&&$money>$contract_r['return_money']){ | ||
153 | + $this->error(__("累计开票金额,不能大于合同金额且不能大于回款金额")); | ||
154 | + } | ||
155 | + | ||
156 | + $params = array_merge($params, [ | ||
157 | + 'create_admin_id' => $this->auth->id, | ||
158 | + 'invoice_admin_id' => 0, | ||
159 | + 'customer_id'=>$contract_r['customer_id'], | ||
160 | + 'status' =>0, | ||
161 | + 'check_status' => 0, | ||
162 | + ]); | ||
163 | + | ||
164 | + $result = false; | ||
165 | + $invoice_id = 0; | ||
166 | + Db::startTrans(); | ||
167 | + try { | ||
168 | + $name = str_replace("\\model\\", "\\validate\\", get_class($this->model)); | ||
169 | + $this->model->validateFailException(true)->validate( $name . '.add'); | ||
170 | + $result = $this->model->allowField(true)->save($params); | ||
171 | + $invoice_id = $this->model->id; | ||
172 | + Db::commit(); | ||
173 | + } catch (ValidateException $e) { | ||
174 | + Db::rollback(); | ||
175 | + $this->error($e->getMessage()); | ||
176 | + } catch (PDOException $e) { | ||
177 | + Db::rollback(); | ||
178 | + $this->error($e->getMessage()); | ||
179 | + } catch (Exception $e) { | ||
180 | + Db::rollback(); | ||
181 | + $this->error($e->getMessage()); | ||
182 | + } | ||
183 | + if ($result !== false) { | ||
184 | + //处理合同审核流程 | ||
185 | + $flow->addFlow($invoice_id, $this->auth->id, 'invoice', $flow_r); | ||
186 | + hook("facrm_invoice_add", array_merge($params, ['id' => $invoice_id])); | ||
187 | + $this->success(); | ||
188 | + } else { | ||
189 | + $this->error(__('No rows were inserted')); | ||
190 | + } | ||
191 | + } | ||
192 | + | ||
193 | + | ||
194 | + $setting=json_decode($setting,true); | ||
195 | + if ($flow_r->config==1)//如果固定审批 | ||
196 | + $flow_r['flow_admin_id']=$flow->getAdminIds($flow_r,$this->auth->id); | ||
197 | + | ||
198 | + $this->success('',array('flow'=>$flow_r,'setting'=>$setting)); | ||
199 | + } | ||
200 | + /** | ||
201 | + * 获取客户历史发票资料 | ||
202 | + * @ApiSummary (用于自动完成发票信息填写) | ||
203 | + * @ApiParams (name="contract_id", type="integer", required=true, description="合同ID") | ||
204 | + * @return mixed | ||
205 | + */ | ||
206 | + public function history($contract_id=NULL){ | ||
207 | + $contract_id = $this->request->request('contract_id', '', 'intval'); | ||
208 | + if (!$this->auth->check('facrm/invoice/add')){ | ||
209 | + $this->error(__('You have no permission')); | ||
210 | + } | ||
211 | + if (!$contract_id) { | ||
212 | + $this->error(__('No Results were found')); | ||
213 | + } | ||
214 | + //获取合同信息 | ||
215 | + $contractModel= new \app\admin\model\facrm\Contract(); | ||
216 | + $contract=$contractModel->where('id',$contract_id)->find(); | ||
217 | + if (!$contract){ | ||
218 | + $this->error(__('合同信息不存在')); | ||
219 | + } | ||
220 | + | ||
221 | + $invoice =$this->model->where('customer_id',$contract->customer_id)->orderRaw("field(check_status,'2','1','0','3')")->order('id desc')->fetchSql(false)->find(); | ||
222 | + | ||
223 | + if ($invoice) { | ||
224 | + $invoice->hidden(['files']); | ||
225 | + } | ||
226 | + | ||
227 | + $this->success('',[ | ||
228 | + 'contract'=>[ | ||
229 | + 'money'=>$contract['money'], | ||
230 | + 'return_money'=>$contract['money'], | ||
231 | + 'invoice_money'=>$contract['invoice_money'] | ||
232 | + ], | ||
233 | + 'invoice'=>$invoice | ||
234 | + ]); | ||
235 | + | ||
236 | + } | ||
237 | + | ||
238 | + | ||
239 | + | ||
240 | + | ||
241 | + | ||
242 | + | ||
243 | + /** | ||
244 | + * 修改 | ||
245 | + * @ApiSummary (用于自动完成发票信息填写) | ||
246 | + * @ApiParams (name="ids", type="integer", required=true, description="ID") | ||
247 | + * @ApiBody ("GET获取参数,【flow审核配置,row发票数据】,POST提交申请,参数参考PC") | ||
248 | + */ | ||
249 | + public function edit($ids = NULL) | ||
250 | + { | ||
251 | + $ids = $this->request->request('ids', '', 'intval'); | ||
252 | + $row = $this->model->get($ids); | ||
253 | + if (!$row) { | ||
254 | + $this->error(__('No Results were found')); | ||
255 | + } | ||
256 | + | ||
257 | + $flow = model('\app\admin\model\facrm\Flow'); | ||
258 | + | ||
259 | + if ($row->flow_id){ | ||
260 | + $flow->where('id',$row->flow_id);//处理流程被删除 | ||
261 | + } | ||
262 | + | ||
263 | + $flow_r = $flow->where('types', 'invoice')->where("status", 1)->find(); | ||
264 | + if ($this->request->isPost()) { | ||
265 | + | ||
266 | + $params = $this->request->post("row/a"); | ||
267 | + if ($params) { | ||
268 | + if ($row->check_status == 2) { | ||
269 | + //审核通过的只能修改负责人和备注、处理情况、续费单价 | ||
270 | + $params_update =array(); | ||
271 | + isset($params['remarks'])?$params_update['remarks']=$params['remarks']:''; | ||
272 | + $result = $row->allowField(true)->save($params_update); | ||
273 | + $this->success(); | ||
274 | + } | ||
275 | + /* elseif ($row->check_status == 1) { | ||
276 | + //审核中的不能修改 | ||
277 | + $this->error(__("审核中的不能修改,请先驳回再修改")); | ||
278 | + }*/ | ||
279 | + $params['check_status'] = 0;//重新改成待审核状态 | ||
280 | + | ||
281 | + //获取合同情况 | ||
282 | + $contract_r = $row->contract; | ||
283 | + if (!$contract_r) | ||
284 | + $this->error(__('没有找到合同')); | ||
285 | + | ||
286 | + | ||
287 | + if ($contract_r['check_status']!=2) | ||
288 | + $this->error(__('合同未通过审核不能申请发票')); | ||
289 | + | ||
290 | + //判断开票金额,不能大于合同金额且不能大于回款金额 | ||
291 | + $money=bcadd($params['money'],$contract_r['invoice_money'],2); | ||
292 | + | ||
293 | + if ($money>$contract_r['money']&&$money>$contract_r['return_money']){ | ||
294 | + $this->error(__("累计开票金额,不能大于合同金额且不能大于回款金额")); | ||
295 | + } | ||
296 | + | ||
297 | + | ||
298 | + $result = false; | ||
299 | + Db::startTrans(); | ||
300 | + try { | ||
301 | + //是否采用模型验证 | ||
302 | + $name = str_replace("\\model\\", "\\validate\\", get_class($this->model)); | ||
303 | + $row->validateFailException(true)->validate($name . '.edit'); | ||
304 | + $invoice_id = $row->id; | ||
305 | + $result = $row->allowField(true)->save($params); | ||
306 | + if ($result) { | ||
307 | + | ||
308 | + } | ||
309 | + Db::commit(); | ||
310 | + } catch (ValidateException $e) { | ||
311 | + Db::rollback(); | ||
312 | + $this->error($e->getMessage()); | ||
313 | + } catch (PDOException $e) { | ||
314 | + Db::rollback(); | ||
315 | + $this->error($e->getMessage()); | ||
316 | + } catch (Exception $e) { | ||
317 | + Db::rollback(); | ||
318 | + $this->error($e->getMessage()); | ||
319 | + } | ||
320 | + if ($result !== false) { | ||
321 | + //处理合同审核流程 | ||
322 | + $flow->addFlow($invoice_id, $this->auth->id, 'invoice', $flow_r); | ||
323 | + hook("facrm_invoice_edit", array_merge($params, ['id' => $invoice_id])); | ||
324 | + $this->success(); | ||
325 | + } else { | ||
326 | + $this->error(__('No rows were updated')); | ||
327 | + } | ||
328 | + } | ||
329 | + $this->error(__('Parameter %s can not be empty', '')); | ||
330 | + } | ||
331 | + $row=$row->toArray(); | ||
332 | + //处理附件 | ||
333 | + if ($row['files']){ | ||
334 | + $row['files']=explode(',',$row['files']); | ||
335 | + foreach ($row['files'] as &$val){ | ||
336 | + $val=cdnurl($val,true); | ||
337 | + } | ||
338 | + } | ||
339 | + | ||
340 | + $this->success('',array('flow'=>$flow_r,'row'=>$row)); | ||
341 | + | ||
342 | + } | ||
343 | + | ||
344 | + /** | ||
345 | + * 开具 | ||
346 | + * @ApiSummary (用于自动完成发票信息填写) | ||
347 | + * @ApiParams (name="ids", type="integer", required=true, description="ID") | ||
348 | + * @ApiBody ("GET获取参数,【row发票数据】,POST提交申请,参数参考PC") | ||
349 | + */ | ||
350 | + public function opener($ids=NULL){ | ||
351 | + $ids = $this->request->request('ids', '', 'intval'); | ||
352 | + //其实就是把发票附件上传 | ||
353 | + $row = $this->model->get($ids); | ||
354 | + if (!$row) { | ||
355 | + $this->error(__('No Results were found')); | ||
356 | + } | ||
357 | + if ($row->status==2){ | ||
358 | + $this->error(__('已开具,不能重复开具')); | ||
359 | + } | ||
360 | + if ($this->request->isPost()){ | ||
361 | + | ||
362 | + $params = $this->request->post("row/a"); | ||
363 | + if ($params) { | ||
364 | + $params['status']=2; | ||
365 | + $result = $row->allowField(true)->save($params); | ||
366 | + if ($result){ | ||
367 | + $row->contract()->setInc('invoice_money', $row->money); | ||
368 | + //钩子 | ||
369 | + hook("facrm_invoice_opener", array_merge($row->toArray(),$params)); | ||
370 | + $this->success("成功"); | ||
371 | + } | ||
372 | + | ||
373 | + | ||
374 | + } | ||
375 | + $this->error(__('No rows were updated')); | ||
376 | + } | ||
377 | + $this->success('',array('row'=>$row)); | ||
378 | + } | ||
379 | + | ||
380 | + | ||
381 | + /** | ||
382 | + * 删除 | ||
383 | + * @param string $ids | ||
384 | + */ | ||
385 | + public function del($ids = "") | ||
386 | + { | ||
387 | + if (!$this->request->isPost()) { | ||
388 | + $this->error(__("Invalid parameters")); | ||
389 | + } | ||
390 | + $ids = $ids ? $ids : $this->request->post("ids"); | ||
391 | + if ($ids) { | ||
392 | + $pk = $this->model->getPk(); | ||
393 | + $this->childrenAdminIds = $this->auth->getChildrenAdminIds(true); | ||
394 | + $list = $this->model->where($pk, 'in', $ids)->where('create_admin_id', 'in', $this->childrenAdminIds)->select(); | ||
395 | + | ||
396 | + $count = 0; | ||
397 | + Db::startTrans(); | ||
398 | + try { | ||
399 | + foreach ($list as $k => $v) { | ||
400 | + $count += $v->delete(); | ||
401 | + } | ||
402 | + Db::commit(); | ||
403 | + } catch (PDOException $e) { | ||
404 | + Db::rollback(); | ||
405 | + $this->error($e->getMessage()); | ||
406 | + } catch (Exception $e) { | ||
407 | + Db::rollback(); | ||
408 | + $this->error($e->getMessage()); | ||
409 | + } | ||
410 | + if ($count) { | ||
411 | + $this->success(); | ||
412 | + } else { | ||
413 | + $this->error(__('No rows were deleted')); | ||
414 | + } | ||
415 | + } | ||
416 | + $this->error(__('Parameter %s can not be empty', 'ids')); | ||
417 | + } | ||
418 | + | ||
419 | + | ||
420 | + /** | ||
421 | + * 处理过滤where条件 | ||
422 | + * @return array | ||
423 | + */ | ||
424 | + private function getFilterWhere($scene_list) | ||
425 | + { | ||
426 | + $filter = $this->request->get("filter", ''); | ||
427 | + $filter = (array)json_decode($filter, true); | ||
428 | + $filter_w = []; | ||
429 | + $filter['scene_id'] = isset($filter['scene_id']) ? $filter['scene_id'] : 1; | ||
430 | + if (isset($filter['scene_id'])) { | ||
431 | + | ||
432 | + if (!isset($scene_list[$filter['scene_id']])) { | ||
433 | + $this->error(__("您没有权限")); | ||
434 | + } | ||
435 | + switch ($filter['scene_id']) { | ||
436 | + case 'all': | ||
437 | + //全部 | ||
438 | + break; | ||
439 | + case 'owner': | ||
440 | + //我的 | ||
441 | + $filter_w['create_admin_id'] = $this->auth->id; | ||
442 | + break; | ||
443 | + case 'branch': | ||
444 | + //下级 | ||
445 | + $this->childrenAdminIds = $this->auth->getChildrenAdminIds(false); | ||
446 | + $filter_w['create_admin_id'] = ['in', $this->childrenAdminIds]; | ||
447 | + break; | ||
448 | + default://其它的未做 TODO | ||
449 | + $filter_w['create_admin_id'] = $this->auth->id; | ||
450 | + } | ||
451 | + unset($filter['scene_id']); | ||
452 | + $this->request->get(['filter' => json_encode($filter)]); | ||
453 | + } | ||
454 | + return $filter_w; | ||
455 | + } | ||
456 | + | ||
457 | + | ||
458 | + | ||
459 | +} |
addons/facrm/controller/facrm/Operatelog.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\facrm\controller\facrm; | ||
4 | + | ||
5 | +use addons\facrm\library\BackendApi; | ||
6 | + | ||
7 | + | ||
8 | + | ||
9 | +/** | ||
10 | + * 操作记录 | ||
11 | + */ | ||
12 | +class Operatelog extends BackendApi | ||
13 | +{ | ||
14 | + | ||
15 | + protected $model = null; | ||
16 | + protected $noNeedRight = ['index']; | ||
17 | + /** | ||
18 | + * 快速搜索时执行查找的字段 | ||
19 | + */ | ||
20 | + protected $searchFields = 'content'; | ||
21 | + | ||
22 | + public function _initialize() | ||
23 | + { | ||
24 | + parent::_initialize(); | ||
25 | + $this->model = model('\app\admin\model\facrm\Operatelog'); | ||
26 | + $this->request->filter(['strip_tags']); | ||
27 | + } | ||
28 | + | ||
29 | + /** | ||
30 | + * 查看 | ||
31 | + * @ApiSummary (参数根据实际需要传,不需要三个都一起传) | ||
32 | + * @ApiMethod (GET) | ||
33 | + * @ApiParams (name="customer_id", type="int", required=false, description="客户ID") | ||
34 | + * @ApiParams (name="contract_id", type="int", required=false, description="合同ID") | ||
35 | + * @ApiParams (name="receivable_id", type="int", required=false, description="回款ID") | ||
36 | + * @ApiBody ("有分页") | ||
37 | + */ | ||
38 | + public function index($customer_id = null, $contract_id = null, $receivable_id = null) | ||
39 | + { | ||
40 | + $customer_id = $customer_id ? $customer_id : $this->request->param("customer_id"); | ||
41 | + $contract_id = $contract_id ? $contract_id : $this->request->param("contract_id"); | ||
42 | + $receivable_id = $receivable_id ? $receivable_id : $this->request->param("receivable_id"); | ||
43 | + | ||
44 | + | ||
45 | + $filter_w = []; | ||
46 | + if ($customer_id) { | ||
47 | + $filter_w['customer_id'] = $customer_id; | ||
48 | + } | ||
49 | + if ($contract_id) { | ||
50 | + $filter_w['contract_id'] = $contract_id; | ||
51 | + } | ||
52 | + if ($receivable_id) { | ||
53 | + $filter_w['receivable_id'] = $receivable_id; | ||
54 | + } | ||
55 | + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); | ||
56 | + | ||
57 | + $total = $this->model | ||
58 | + ->where($where) | ||
59 | + ->where($filter_w) | ||
60 | + ->order($sort, $order)->fetchSql(false) | ||
61 | + ->count(); | ||
62 | + $list = $this->model | ||
63 | + ->where($filter_w) | ||
64 | + ->where($where) | ||
65 | + ->order($sort, $order) | ||
66 | + ->limit($offset, $limit)->fetchSql(false) | ||
67 | + ->select(); | ||
68 | + foreach ($list as $row) { | ||
69 | + $row->hidden(['content']); | ||
70 | + } | ||
71 | + $result = array("total" => $total, "rows" => $list); | ||
72 | + $this->success('', $result); | ||
73 | + } | ||
74 | + | ||
75 | + | ||
76 | + /** | ||
77 | + * 日志详情 | ||
78 | + * @ApiParams (name="ids", type="int", required=true, description="日志ID") | ||
79 | + */ | ||
80 | + public function detail($ids = NULL) | ||
81 | + { | ||
82 | + $ids = $ids ? $ids : $this->request->param("ids"); | ||
83 | + $row = $this->model->get(['id' => $ids]); | ||
84 | + if (!$row) { | ||
85 | + $this->error(__('No Results were found')); | ||
86 | + } | ||
87 | + $this->success('', $row->toArray()); | ||
88 | + } | ||
89 | + | ||
90 | + | ||
91 | +} |
-
请 注册 或 登录 后发表评论