作者 黄张义

提交

要显示太多修改。

为保证性能只显示 25 of 25+ 个文件。

open_basedir=/www/wwwroot/CRM/:/tmp/
\ No newline at end of file
... ...
deny from all
\ No newline at end of file
... ...
{"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"]}
\ No newline at end of file
... ...
<?php
namespace addons\facrm;
use app\admin\model\facrm\Contract;
use app\common\library\Menu;
use fast\Tree;
use think\Addons;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use think\exception\ValidateException;
use think\Queue;
use think\Cookie;
/**
* 插件
*/
class Facrm extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
$menu = [];
$config_file = ADDON_PATH . "facrm" . DS . 'config' . DS . "menu.php";
if (is_file($config_file)) {
$menu = include $config_file;
}
if ($menu) {
Menu::create($menu);
}
/**
* 增加手机号字段
*/
$database=config('database');
$isexits=Db::query("SELECT 1 FROM information_schema.COLUMNS WHERE table_name='{$database['prefix']}admin' AND COLUMN_NAME='mobile' limit 1");
if (!$isexits){
Db::query("ALTER TABLE {$database['prefix']}admin ADD mobile VARCHAR(20) NULL COMMENT '手机'");
}
//首次安装创建表并导入测试数据
\think\addons\Service::importsql('facrm');
if (version_compare(config('fastadmin.version'), '1.3.0', '<') && Db::name("facrm_customer")->count() == 0) {
$this->importData('testdata','');
}
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
$info = get_addon_info('facrm');
Menu::delete(isset($info['first_menu']) ? $info['first_menu'] : 'facrm');
return true;
}
/**
* 插件启用方法
*/
public function enable()
{
$info = get_addon_info('facrm');
Menu::enable(isset($info['first_menu']) ? $info['first_menu'] : 'facrm');
}
/**
* 插件禁用方法
*/
public function disable()
{
$info = get_addon_info('facrm');
Menu::disable(isset($info['first_menu']) ? $info['first_menu'] : 'facrm');
}
/**
* 插件升级方法
*/
public function upgrade()
{
$menu = include ADDON_PATH . 'facrm' . DS . 'config' . DS . 'menu.php';
Menu::upgrade('facrm', $menu);
/**
* 增加手机号字段
*/
$database=config('database');
$isexits=Db::query("SELECT 1 FROM information_schema.COLUMNS WHERE table_name='{$database['prefix']}admin' AND COLUMN_NAME='mobile' limit 1");
if (!$isexits){
Db::query("ALTER TABLE {$database['prefix']}admin ADD mobile VARCHAR(20) NULL COMMENT '手机'");
}
}
/**
* 登录后 不跟进和未成交的客户处理
*/
public function adminLoginInit()
{
$config = $this->getConfig();
//不跟进 lose_day1 //不成交lose_day2
if ($config['lose_day1'] > 0 || ($config['lose_day2'] > 0)) {
$customerModel = model('\app\admin\model\facrm\Customer');
$customerModel->where('deal_status', 0)->where('owner_user_id', 'gt', 0);
if ($config['lose_day1'] > 0 && $config['lose_day2'] > 0) {
//如果不跟进和不成交都开启,掉入公海逻辑
$customerModel->where(function ($query) use ($config) {
$query->where('follow_time', '<', (time() - $config['lose_day1'] * 86400))->where('follow_time', 'gt', 0)->whereOr('collect_time', '<', (time() - $config['lose_day2'] * 86400));
});
} elseif ($config['lose_day1'] > 0 && ($config['lose_day2'] <= 0)) {
//如果只开启不跟进,掉入公海逻辑
$customerModel->where('follow_time', '<', (time() - $config['lose_day1'] * 86400))->where('follow_time', 'gt', 0);
} elseif ($config['lose_day1'] <= 0 && $config['lose_day2'] > 0) {
//如果只开启不成交,掉入公海逻辑
$customerModel->where('collect_time', '<', (time() - $config['lose_day2'] * 86400));
} else {
return true;
}
$lists = $customerModel->fetchSql(false)->select();
if ($lists) {
foreach ($lists as $row) {
$owner_user_id = $row->owner_user_id;
$row->discard();
\app\admin\model\AdminLog::create([
'title' => __("客户过期自动加入公海"),
'content' => json_encode(['id' => $row->id, 'name' => $row->name], JSON_UNESCAPED_UNICODE),
'url' => "customer/discard",
'admin_id' => $owner_user_id,
]);
}
}
}
}
/**
* 登录后
*/
public function adminLoginAfter($request){
$exten_type=$request->request('exten_type','');
$from_exten=$request->request('from_exten','','htmlentities');//工号
\think\Cookie::set("facrm_extentype", $exten_type?$exten_type:'',86400 * 7);//云呼通话方式
Cookie::set("facrm_from_exten", $from_exten?$from_exten:'',86400 * 7);
if($from_exten){
\app\admin\model\facrm\Cloudcall::edit('','',$from_exten,true);
}
}
/**
* 审核成功钩子
* @param $param
*/
public function facrmFlowVerify(&$param)
{
if (!isset($param['types'])) return false;
$check_status=($param['is_end'] == 1&&$param['status']==1)?2:(($param['status']==0)?3:1);
switch ($param['types']) {
case 'receivables':
if ($param['is_end'] == 1 && $param['status'] == 1) {
$receivablesModel = new \app\admin\model\facrm\contract\Receivables();
//$contractModel=new \app\admin\model\facrm\Contract();
$receivables = $receivablesModel::get($param['types_id']);
$receivables->contract()->setInc('return_money', $receivables->money);
$receivables->plan()->update(['status'=>2,'return_money'=>\think\Db::raw("`return_money`+{$receivables['money']}")]);
}
//1审核中、2审核通过、3审核未通过
break;
case "contract":
if ($param['is_end'] == 1 && $param['status'] == 1) {
$contractModel = new \app\admin\model\facrm\Contract();
$contract = $contractModel::get($param['types_id']);
$contract->customer()->update([
'deal_status' => 1, 'deal_time' => time(),
'purchase_times'=> Db::raw('purchase_times+1'),
'purchase_total'=> Db::raw('purchase_total+'.$contract->money),
]);
//如果有商机也改成成交状态
if ($contract->business_id) {
$contract->business()->update(['is_end' => 1, 'deal_time' => time()]);//把商机改成成交状态
}
}
break;
default:
}
//消息通知
try {
Queue::push("addons\\facrm\\library\\notice\queue\\Flow" . ucfirst($param['types']) . "Job",
['model_id' => $param['types_id'], 'data' => ['check_status' => $check_status]]);
} catch (\Exception $e) {
}
//消息通知end
return true;
}
/**
* 用户注册成功钩子
*/
public function userRegisterSuccessed(&$user)
{
return \addons\facrm\library\Helper::synUser($user);
}
/**
* 发送邮件成功钩子
*param_data types类型如customer,contacts| typesid对应的ID
*send_data发送邮件的内容
*types_data 当前对象的数据
* @param $param
*/
public function facrmSendEmailSuccess($param)
{
if (!isset($param['param_data']) || !$param['param_data'] || !isset($param['send_data']) || !$param['send_data']) return false;
return $this->addRecord($param['param_data'], $param['send_data'], __("发送邮件"));
}
/**
* 发送短息成功钩子
*param_data types类型如customer,contacts| typesid对应的ID
*send_data发送短息的内容
*types_data 当前对象的数据
* @param $param
*/
public function facrmSendSmsSuccess($param)
{
if (!isset($param['param_data']) || !$param['param_data'] || !isset($param['send_data']) || !$param['send_data']) return false;
return $this->addRecord($param['param_data'], $param['send_data'], __("发送短息"));
}
/**
* 自动添加跟进
* @param $param_data
* @param $send_data
* @param string $df_content
* @return bool
* @throws \think\exception\DbException
*/
private function addRecord($param_data, $send_data, $df_content = "")
{
$result = false;
$record_data = array();
if ($param_data && $param_data['types']) {
switch ($param_data['types']) {
case "customer":
//跟进客户
$customer = model('\app\admin\model\facrm\Customer');
$rowc = $customer->get($param_data['typesid']);
if (!$rowc) return false;
$rowc->follow_time = time();
$rowc->save();
$record_data['types'] = "customer";
$record_data['types_id'] = $rowc->id;
break;
case "business":
$business = model('\app\admin\model\facrm\Business');
$row = $business->get($param_data['typesid']);
if (!$row) return false;
//更新客户表
$row->customer()->update(["follow_time" => time()]);
$row->save();
$record_data['types'] = "business";
$record_data['types_id'] = $row->id;
break;
case "contacts":
//跟进客户
$contactsModel = model('\app\admin\model\facrm\customer\Contacts');
$contacts = $contactsModel->get($param_data['typesid']);
if (!$contacts || !$contacts->customer) return false;
$contacts->customer->follow_time = time();
$contacts->customer->save();
$record_data['types'] = "customer";
$record_data['types_id'] = $contacts->customer_id;
$send_data['content']=(isset($send_data['content']) ? $send_data['content'] : $df_content)."【联系人:{$contacts['name']}】";
break;
case "clues":
//跟进线索
$cluesModel = model('\app\admin\model\facrm\Clues');
$rowc = $cluesModel->get($param_data['typesid']);
if (!$rowc) return false;
$rowc->follow_time = time();
$rowc->save();
$record_data['types'] = "clues";
$record_data['types_id'] = $rowc->id;
break;
default:
break;
}
}
if ($record_data) {
(new \app\admin\model\facrm\Record)->allowField(true)->save(array_merge($record_data, [
'content' => strip_tags(isset($send_data['content']) ? $send_data['content'] : $df_content),
'record_type' => isset($send_data['record_type']) ? $send_data['record_type'] : 0,//跟进类型
'create_user_id' => isset($send_data['create_user_id']) ? $send_data['create_user_id'] : 0,
]));
}
return $result;
}
/**
* 导入数据
*/
protected function importData($sqlname="",$dir='config')
{
$sqlFile = ADDON_PATH . 'facrm' . ($dir?DS.$dir:'').DS .$sqlname.'.sql';
if (is_file($sqlFile)) {
$lines = file($sqlFile);
$templine = '';
foreach ($lines as $line) {
if (substr($line, 0, 2) == '--' || $line == '' || substr($line, 0, 2) == '/*') {
continue;
}
$templine .= $line;
if (substr(trim($line), -1, 1) == ';') {
$templine = str_ireplace('__PREFIX__', config('database.prefix'), $templine);
$templine = str_ireplace('INSERT INTO ', 'INSERT IGNORE INTO ', $templine);
try {
Db::getPdo()->exec($templine);
} catch (\Exception $e) {
echo $e->getMessage();
}
$templine = '';
}
}
}
}
/**
* 手机号脚本替换
*/
public function viewFilter(& $content)
{
$module = strtolower(request()->module());
$controller=strtolower(request()->controller());
$action=strtolower(request()->action());
if ($module == 'admin'&&$controller=='auth.admin'&&version_compare(config('fastadmin.version'), '1.3.4', '<')) {
$view=\think\View::instance();
$mobile=isset($view->row->mobile)?$view->row->mobile:'';
$str_rp='<div class="form-group hidden layer-footer">';
$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>';
$content = preg_replace_callback("/{$str_rp}/i", function ($matches) use ($new_rp,$str_rp){
return $new_rp.$str_rp;
}, $content);
}
if ($module == 'admin'&&$controller=='index'&&$action=='index') {
$view=\think\View::instance();
if (!isset($view->auth)) return true;
//获取合同\,回款待审批
$contractModel= new Contract();
$receivablesModel=new \app\admin\model\facrm\contract\Receivables();
$invoiceModel=new \app\admin\model\facrm\Invoice();
$filter_w['check_status'] =['in',[0,1]];
$total = $contractModel->where($filter_w)->where('','exp','FIND_IN_SET('. $view->auth->id.',flow_admin_id)')->fetchSql(false)->count();
$total +=$receivablesModel->where($filter_w)->where('','exp','FIND_IN_SET('.$view->auth->id.',flow_admin_id)')->fetchSql(false)->count();
$total +=$invoiceModel->where($filter_w)->where('','exp','FIND_IN_SET('.$view->auth->id.',flow_admin_id)')->fetchSql(false)->count();
$content =$content."<script>function setsidebar(){Backend.api.sidebar({'facrm/backlog':{$total},'facrm':{$total}})}; setTimeout('setsidebar()','5000');</script>";
}
//云呼方式
if ($module == 'admin'&&$controller=='index'&&$action=='login') {
//获取云呼配置
$all_types = \addons\facrm\library\cloudcall\Call::getProviders();
$keys = "";
foreach ($all_types as $v) {
$keys .= $keys ? ',' .'cloudcall'. $v : 'cloudcall' . $v;
}
$settingModel = new \app\admin\model\facrm\Setting();
$setting= $settingModel->where('key', 'in', $keys)->where('status', 1)->find();//只找一条云呼通道
if (!$setting) return true;
$setting=$setting['values'];
$exten_type=Cookie::get("facrm_extentype");//云呼通话方式
$from_exten=htmlentities(Cookie::get("facrm_from_exten"));//云呼通话坐席工号
$str_rp='<div class="form-group checkbox">';
$new_rp="";
if (isset($setting['open_exten'])&&$setting['open_exten']){
$new_rp=' <div class="input-group">
<div class="input-group-addon"><span class="glyphicon fa fa-phone" aria-hidden="true"></span></div>
<input type="text" class="form-control" placeholder="云呼工号,如不知道可留空" name="from_exten" value="'.$from_exten.'" />
</div>';
}
$new_rp.=' <div class="input-group">
<div class="input-group-addon"><span class="glyphicon fa fa-phone" aria-hidden="true"></span></div>
<select class="form-control selectpicker" name="exten_type"><option value=""> 请选择云呼方式</option>
<option value="Local" '.($exten_type=='Local'?'selected':'').'>工作手机</option>
<option value="sip" '.($exten_type=='sip'?'selected':'').'>软电话</option>
<option value="gateway" '.($exten_type=='gateway'?'selected':'').'>话机方式</option>
</select>
</div>';
$content = preg_replace_callback("/{$str_rp}/i", function ($matches) use ($new_rp,$str_rp){
return $new_rp.$str_rp;
}, $content);
}
}
/**
* 发票开具钩子
* @param $param
*/
public function facrmInvoiceOpener($param){
//通知
Queue::push("addons\\facrm\\library\\notice\queue\\InvoiceJob", [
'model_id'=>$param['id'],
]);
}
}
... ...
{php}
$ignore=[
'diy_text','deal_status','deal_time','is_lock',
'level','industry','tags','source',"id",
'create_user_id','owner_user_id','user_id','ro_user_id',
'rw_user_id','province','city','area',
'lng','lat','city','next_time',
];
$customer_fields=\addons\facrm\library\Helper::getfield('customer','*',['infinity'=>__("不限制唯一字段")],$ignore);
{/php}
<form id="config-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="">
{if $addon.tips}
<div class="alert {$addon.tips.extend|default='alert-info-light'}" style="margin-bottom:10px;">
<b>{$addon.tips.title|htmlentities}</b><br>
{$addon.tips.value|htmlentities}
</div>
{/if}
<table class="table table-striped">
<thead>
<tr>
<th width="15%">{:__('Title')}</th>
<th width="85%">{:__('Value')}</th>
</tr>
</thead>
<tbody>
{foreach $addon.config as $item}
<tr>
<td>{$item.title|htmlentities}</td>
<td>
<div class="row">
<div class="col-sm-8 col-xs-12">
{switch $item.type}
{case string}
<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}"/>
{/case}
{case text}
<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>
{/case}
{case array}
<dl class="fieldlist" data-name="row[{$item.name|htmlentities}]">
<dd>
<ins>{:__('键')}</ins>
<ins>{:__('值')}</ins>
</dd>
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[{$item.name|htmlentities}]" cols="30" rows="5" class="hide">{$item.value|json_encode|htmlentities}</textarea>
</dl>
{/case}
{case date}
<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}"/>
{/case}
{case time}
<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}"/>
{/case}
{case datetime}
<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}"/>
{/case}
{case number}
<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}"/>
{/case}
{case checkbox}
{foreach name="item.content" item="vo"}
<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>
{/foreach}
{/case}
{case radio}
{foreach name="item.content" item="vo"}
<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>
{/foreach}
{/case}
{case value="select" break="0"}{/case}
{case value="selects"}
{php}
if($item['name']==='unique'){
$item['content']=$customer_fields;
}
{/php}
<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':''}>
{foreach name="item.content" item="vo"}
<option value="{$key|htmlentities}" {in name="key" value="$item.value" }selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
{/case}
{case value="image" break="0"}{/case}
{case value="images"}
<div class="input-group">
<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}">
<div class="input-group-addon no-border no-padding">
<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>
<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>
</div>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span>
</div>
<ul class="row list-inline faupload-preview" id="p-{$item.name|htmlentities}"></ul>
{/case}
{case value="file" break="0"}{/case}
{case value="files"}
<div class="input-group">
<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}">
<div class="input-group-addon no-border no-padding">
<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>
<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>
</div>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span>
</div>
<ul class="row list-inline faupload-preview" id="p-{$item.name|htmlentities}"></ul>
{/case}
{case bool}
<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>
<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>
{/case}
{default /}{$item.value|htmlentities}
{/switch}
</div>
<div class="col-sm-4"></div>
</div>
</td>
</tr>
{/foreach}
</tbody>
</table>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
<script>
require.callback = function () {
var tabevent = function () {
$(document).on("click", ".nav-group li a[data-toggle='tab']", function () {
var type = $(this).attr("href").substring(1);
if (type == 'all') {
$(".table-config tr").show();
} else {
$(".table-config tr").hide();
$(".table-config tr[data-type='" + type + "']").show();
}
});
};
define('backend/addon', ['jquery', 'form'], function ($, Form) {
var Controller = {
config: function () {
Form.api.bindevent($("form[role=form]"));
tabevent();
}
};
return Controller;
});
define('backend/facrm/apps/config', ['jquery', 'form'], function ($, Form) {
var Controller = {
index: function () {
Form.api.bindevent($("form[role=form]"));
tabevent();
}
};
return Controller;
});
}
</script>
... ...
<?php
return [
[
'type' => 'array',
'name' => 'level',
'title' => '客户级别',
'value' => [
1 => '重点客户',
'优质客户',
'普通客户',
'0' =>'无级别',
'10000' =>'其它',
],
'content' => [
'value1' => 'title1',
'value2' => 'title2',
],
'tip' => '',
'rule' => '',
'extend' => '',
],
[
'type' => 'array',
'name' => 'industry',
'title' => '行业',
'value' => [
1 => '金融业',
'房地产',
'商业服务',
'贸易',
'运输物流',
'服务业',
'文化传媒',
'IT/互联网',
'其它',
],
'content' => [
'value1' => 'title1',
'value2' => 'title2',
],
'tip' => '',
'rule' => '',
'extend' => '',
],
[
'type' => 'array',
'name' => 'source',
'title' => '客户来源',
'value' => [
1 => '个人资源',
'广告',
'转介绍',
'搜索引擎',
'公司资源',
'电话咨询',
'官网咨询',
'公众号',
'抖音',
'企业微信',
100000 => '其它',
0 => '无来源',
],
'content' => [
'value1' => 'title1',
'value2' => 'title2',
],
'tip' => '',
'rule' => '',
'extend' => '',
],
[
'type' => 'array',
'name' => 'record_type',
'title' => '跟进方式',
'value' => [
1 => '电话',
'上门拜访',
'微信',
'短息',
],
'content' => [
'value1' => 'title1',
'value2' => 'title2',
],
'tip' => '',
'rule' => '',
'extend' => '',
],
[
'type' => 'array',
'name' => 'account',
'title' => '收款账户',
'value' => [
1 => '现金',
'对公账户',
'支付宝',
'微信',
'其它',
],
'content' => [
'value1' => 'title1',
'value2' => 'title2',
],
'tip' => '',
'rule' => '',
'extend' => '',
],
[
'type' => 'number',
'name' => 'possess_num',
'title' => '可拥有客户',
'value' => '-1',
'content' => '',
'tip' => '限制一个员工能拥有的非成交客户数量。-1不限制',
'rule' => '',
'extend' => '',
],
[
'type' => 'number',
'name' => 'lose_day1',
'title' => '不跟进自动公海天数',
'value' => '-1',
'content' => '',
'tip' => '多少天不跟进自动成为公海-1关闭',
'rule' => '',
'extend' => '',
],
[
'type' => 'number',
'name' => 'lose_day2',
'title' => '不成交自动公海天数',
'value' => '-1',
'content' => '',
'tip' => '和跟进天数是或者关系-1关闭',
'rule' => '',
'extend' => '',
],
[
'type' => 'select',
'name' => 'unique',
'title' => '客户唯一字段',
'value' => 'name',
'content' => [
'name' => '客户名称',
'mobile' => '手机',
],
'tip' => '校验客户唯一的字段',
'rule' => '',
'extend' => '',
],
[
'type' => 'radio',
'name' => 'show_contacts',
'title' => '显示联系',
'value' => '1',
'content' => [
1 => '显示',
'隐藏',
],
'tip' => '是否在客户列表显示手机和电话',
'rule' => '',
'extend' => '',
],
[
'type' => 'string',
'name' => 'min_app_id',
'title' => '小程序AppID',
'value' => '',
'content' => '',
'tip' => '',
'rule' => '',
'extend' => '',
],
[
'type' => 'string',
'name' => 'min_app_secret',
'title' => '小程序Secret',
'value' => '',
'content' => '',
'tip' => '',
'rule' => '',
'extend' => '',
],
[
'type' => 'string',
'name' => 'map_qq_key',
'title' => '腾讯地图KEY',
'value' => '',
'content' => '',
'tip' => '',
'rule' => '',
'extend' => '',
],
[
'type' => 'string',
'name' => 'cprefix',
'title' => '合同前缀',
'value' => '{:Y}{:m}{:d}{:h}{:i}{:s}{:rand}',
'content' => '',
'tip' => '{:Y}年,{:m}月,{:d}日,{:h}时,{:i}分{:s}秒,{:rand}6位随机数',
'rule' => '',
'extend' => '',
],
[
'type' => 'string',
'name' => 'rprefix',
'title' => '回款前缀',
'value' => '{:Y}{:m}{:d}{:h}{:i}{:s}{:rand}',
'content' => '',
'tip' => '{:Y}年,{:m}月,{:d}日,{:h}时,{:i}分{:s}秒,{:rand}6位随机数',
'rule' => '',
'extend' => '',
],
[
'type' => 'radio',
'name' => 'deal',
'title' => '手动成交',
'value' => '0',
'content' => [
1 => '开启',
0 => '关闭',
],
'tip' => '开启可在跟进成交客户,不需要经过合同流程',
'rule' => '',
'extend' => '',
],
];
... ...
<?php
return array (
'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',
'self_path' => 'public/assets/addons/facrm
application/admin/lang/zh-cn/facrm',
'update_data' => '--
-- 1.0.1
-- 添加名称字段user_id
--
ALTER TABLE `__PREFIX__facrm_customer` ADD COLUMN `user_id` int(11) NULL DEFAULT \'\' COMMENT \'前台用户ID\' AFTER `owner_user_id`;
--
-- 1.0.3
-- 更改表编码和字段编码和增加字段
--
ALTER TABLE `__PREFIX__facrm_customer` DEFAULT CHARACTER SET utf8mb4,
MODIFY COLUMN `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT \'客户名称\' ,
MODIFY COLUMN `remark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT \'备注\' ;
ALTER TABLE `__PREFIX__facrm_customer_contacts` DEFAULT CHARACTER SET utf8mb4,
MODIFY COLUMN `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT \'姓名\' ,
MODIFY COLUMN `remark` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT \'备注\' ;
ALTER TABLE `__PREFIX__facrm_record` DEFAULT CHARACTER SET utf8mb4,
MODIFY COLUMN `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT \'跟进内容\' ;
ALTER TABLE `__PREFIX__facrm_setting` ADD COLUMN `status` tinyint(1) NULL DEFAULT \'1\' COMMENT \'状态\' AFTER `create_time`;
--
-- 2.0.0
-- 更改表编码和字段编码和增加字段
--
ALTER TABLE `__PREFIX__facrm_record`
MODIFY COLUMN `types` enum(\'business\',\'clues\',\'customer\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT \'customer\' COMMENT \'关联类型(customer跟进,business商机跟进,clues线索)\' AFTER `id`;
ALTER TABLE `__PREFIX__facrm_record_files`
MODIFY COLUMN `types` enum(\'business\',\'clues\',\'customer\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT \'customer\' COMMENT \'关联类型(customer客户,business商机,clues线索)\' AFTER `id`;
--
-- 插入一些必须数据
--
INSERT INTO __PREFIX__facrm_flow VALUES (\'1\', \'合同审批\', \'0\', \'contract\', \'0\', \'\', \'\', \'\', \'1610787200\', \'1610787643\', \'1\', null,1);
INSERT INTO __PREFIX__facrm_flow VALUES (\'2\', \'回款审批\', \'0\', \'receivables\', \'0\', \'\', \'\', \'\', \'1610947811\', \'1618023534\', \'1\', null,2);
INSERT INTO __PREFIX__facrm_flow VALUES (\'3\', \'发票申请\', \'0\', \'invoice\', \'0\', \'\', \'\', \'\', \'1610947811\', \'1618023534\', \'1\', null,3);
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\');
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\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'1\', \'customer\', \'全部客户\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'2\', \'customer\', \'我的客户\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'3\', \'customer\', \'下属客户\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'4\', \'contacts\', \'全部\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'5\', \'contacts\', \'我的\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'6\', \'contacts\', \'下属\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'7\', \'business\', \'全部商机\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'8\', \'business\', \'我的商机\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'9\', \'business\', \'下属商机\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'10\', \'clues\', \'全部线索\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'11\', \'clues\', \'我的线索\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
INSERT INTO __PREFIX__facrm_scene VALUES (\'12\', \'clues\', \'下属线索\', \'0\', \'1\', null, \'1\', \'\', \'0\', \'0\');
--
-- 2.0.2
-- 添加来源字段
--
ALTER TABLE `__PREFIX__facrm_contract`
ADD COLUMN `source_id` int(11) NULL DEFAULT 0 COMMENT \'来源ID\' AFTER `contacts_id`;
--
-- 2.0.5
-- 增加云呼方式
--
ALTER TABLE `__PREFIX__facrm_cloudcall`
MODIFY COLUMN `exten_type` enum(\'gateway\',\'sip\',\'local\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT \'local\' COMMENT \'接听方式Local为“手机”\' AFTER `from_exten`;
--
-- 2.0.6
-- 增加线上收款
--
ALTER TABLE `__PREFIX__facrm_record`
ADD COLUMN `lng` double(14,11) NULL COMMENT \'经度\' AFTER `delete_time`,
ADD COLUMN `lat` double(14,11) NULL COMMENT \'维度\' AFTER `lng`;
ALTER TABLE `__PREFIX__facrm_contract_receivables`
ADD COLUMN `pay_status` tinyint(4) NULL DEFAULT 0 COMMENT \'在线支付状态1已付款0未付款\' AFTER `delete_time`,
ADD COLUMN `pay_type` tinyint(4) NULL DEFAULT 1 COMMENT \'收款方式1默认2在线收款3续费\' AFTER `pay_status`,
ADD COLUMN `pay_token` varchar(200) NULL COMMENT \'访问支付的token\' AFTER `pay_type`;
--
-- 2.0.7
-- 发票
--
ALTER TABLE `__PREFIX__facrm_flow`
ADD COLUMN `weigh` int(11) NULL DEFAULT 0 COMMENT \'权重\' AFTER `delete_time`,
MODIFY COLUMN `types` enum(\'contract\',\'invoice\',\'receivables\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT \'关联对象\' AFTER `config`;
ALTER TABLE `__PREFIX__facrm_flow_log`
MODIFY COLUMN `types` enum(\'contract\',\'invoice\',\'receivables\') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT \'关联对象\' AFTER `flow_id`;
ALTER TABLE `__PREFIX__facrm_contract`
ADD COLUMN `invoice_money` decimal(10,2) NULL DEFAULT 0.00 COMMENT \'已开票金额\' ;
--
-- 2.0.8
-- 消费总额和次数
--
ALTER TABLE `__PREFIX__facrm_customer`
ADD COLUMN `purchase_total` decimal(18,2) NULL DEFAULT 0 COMMENT \'消费总额\' AFTER `qq`,
ADD COLUMN `purchase_times` int(10) NULL DEFAULT 0 COMMENT \'消费次数\' AFTER `purchase_total`;
-- 2.0.10
INSERT INTO `__PREFIX__facrm_scene` (`id`, `types`, `name`, `admin_id`, `create_time`, `update_time`) VALUES (13,\'customer\', \'分享给他人\', \'0\', \'0\', \'0\');
INSERT INTO `__PREFIX__facrm_scene` (`id`,`types`, `name`, `admin_id`, `create_time`, `update_time`) VALUES (14,\'customer\', \'分享给我的\', \'0\', \'0\', \'0\');
--2.1.0
-- 增加自定义跟进状态
ALTER TABLE `__PREFIX__facrm_customer`
ADD COLUMN `follow_status` enum(\'1\',\'2\',\'3\',\'4\',\'5\',\'0\') DEFAULT \'1\' COMMENT \'跟进状态\';
ALTER TABLE `__PREFIX__facrm_clues`
ADD COLUMN `follow_status` enum(\'1\',\'2\',\'3\',\'4\',\'5\',\'0\') DEFAULT \'1\' COMMENT \'跟进状态\';
--2.2.5
-- 增加回款计划
ALTER TABLE `__PREFIX__facrm_contract_receivables`
ADD COLUMN `plan_id` int(11) NOT NULL DEFAULT 0 COMMENT \'关联回款计划\' AFTER `pay_token`;
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\');
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\');
',
);
\ No newline at end of file
... ...
<?php
/**
* 自定义表排序
*/
return array(
array("field" => 'id', "title" => '线索ID', "sortable" => true),
array("field" => 'name', "title" => '线索名称', "operate" => "LIKE", "align" => 'left', 'customField' => 'tags', "class" => "tabletd",
"formatter" => '(function (value, row, index) {
value=\'<a href="javascript:void(0);" data-url="facrm/clues/index/edit/ids/\' + row.id
+\'" data-area="[&quot;98%&quot;,&quot;98%&quot;]" class="btn-dialog" data-title="\'+ row.name+\'">\'+ row.name+\'</a>\';
return value +
\'<div >\' + Table.api.formatter.flag.call(this, row[\'tags\'], row, index) + \'</div>\';
})',
"cellStyle" => '(function(value, row, index, field){return {css: {"max-width":"200px"}};})'),
array("field" => 'tags', "title" => '标签', "visible" => false, "formatter" => "Table.api.formatter.flag", "operate" => 'find_in_set'),
array("field" => 'level', "title" => '级别', "formatter" => "Table.api.formatter.status", "searchList" => 'levelList'),
array("field" => 'industry', "title" => '行业', "formatter" => "(function (v, row, index) {
if(!v) return '无';
return industryList[v];
})", "searchList" => 'industryList'),
array("field" => 'source', "title" => '来源', "formatter" => "(function (v, row, index) {
if(!v) return '无';
return sourceList[v];
})", "searchList" => 'sourceList'),
array("field" => 'telephone', "title" => '电话', "operate" => "LIKE"),
array("field" => 'mobile', "title" => '手机', "operate" => "LIKE"),
array("field" => 'remark', "title" => '备注', "operate" => "LIKE", "class" => "tabletd", "align" => "left", "cellStyle" => "(function(value, row, index, field){
return {css: { \"max-width\":\"250px\"}};
})"),
array("field" => 'status', "title" => '状态', "formatter" => "Table.api.formatter.status", "searchList" => 'status_obj'),
array("field" => 'owner_user_id', "title" => '负责人', "addclass" => "selectpage", "class" => "tabletd", "cellStyle" => "(function(value, row, index, field){
return {css: { \"max-width\":\"200px\"}};
})",
'formatter' => "(function (v, r) {
if (!r.owner_user) return '-';
return r.owner_user.nickname;})",
'extend' => 'data-source="facrm/common/selectpage/model/admin?type=children" data-field="nickname" data-orderBy="id desc"'
),
array("field" => 'create_user_id', "title" => '创建人', "addclass" => "selectpage", "formatter" => '(function (v, r) {
if (!r.create_user) return \'-\';
return r.create_user.nickname;
})',
"extend" => 'data-source="facrm/common/selectpage/model/admin?type=children" data-field="nickname" data-orderBy="id desc"',
),
array("field" => 'next_time', "title" => '下次跟进', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'follow_time', "title" => '最近跟进', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'create_time', "title" => '创建时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'collect_time', "title" => '领取时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'update_time', "title" => '更新时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
);
... ...
<?php
/**
* 合同自定义表排序
*/
return array(
array("field" => 'id', "title" => '合同ID', "sortable" => true),
array("field" => 'number', "title" => '合同编号', "operate" => "LIKE", "align" => 'left',
"formatter" => '(function (value, row, index) {
return \'<a href="javascript:void(0);" data-url="facrm/contract/index/detail/ids/\' + row.id
+ \'" data-area="[&quot;98%&quot;,&quot;98%&quot;]" class="btn-dialog" data-title="\' + value + \'">\' + value + \'</a>\';
})',),
array("field" => 'name', "title" => '合同名称', "operate" => "LIKE", "align" => 'left',
"formatter" => '(function (value, row, index) {
//判断是否逾期
var newtime = Math.round(new Date().getTime() / 1000).toString();
if (newtime > row.end_time)
value = \'<span class="label label-danger">过期</span>\' + value;
return value;
})',),
array("field" => 'customer_id', "title" => '客户名称', "align" => 'left',
"formatter" => '(function (value, row, index) {
if (!row.customer) return \'-\';
return \'<a href="javascript:void(0);" data-url="facrm/customer/index/detail/ids/\' + row.customer.id
+ \'" data-area="[&quot;98%&quot;,&quot;98%&quot;]" class="btn-dialog" data-title="\' + row.customer.name + \'">\' + row.customer.name + \'(\' + row.customer_id + \')\' + \'</a>\';
})',
"addclass" => "selectpage", 'extend' => 'data-source="facrm/customer/index?filter=%7B\"scene_id\"%3A\"1\"%7D" data-field="name" data-orderBy="id desc"'),
array("field" => 'money', "title" => '合同金额', "sortable" => true, 'operate' => 'BETWEEN'),
array("field" => 'return_money', "title" => '回款金额', "sortable" => true, 'operate' => 'BETWEEN'),
array("field" => 'order_time', "title" => '下单时间', "sortable" => true, 'operate' => 'RANGE', "formatter" => "Table.api.formatter.datetime",
'datetimeFormat'=>"YYYY/MM/DD","extend"=>'autocomplete="off" data-time-picker="true"','addclass'=>'datetimerange'),
array("field" => 'remark', "title" => '备注', "align" => "left", 'operate' => 'LIKE'),
array("field" => 'start_time', "title" => '开始时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'end_time', "title" => '结束时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'product', "title" => '订购商品', "operate" => false, "align" => 'left',
"formatter" => '(function (value, row, index) {
if (!value||value.length == 0) {
return "商品有误";
}
text = "";
for (i = 0; i < value.length; i++) {
text += "编码:" + value[i].sku + "|数量:" + value[i].nums +"|" + value[i].name + "" + " <br>";
}
return Table.api.formatter.content(text, row, index);
})',),
array("field" => 'create_user_id', "title" => '创建人', "addclass" => "selectpage", "formatter" => '(function (v, r) {
if (!r.create_user) return \'-\';
return r.create_user.nickname;
})',
"extend" => 'data-source="facrm/common/selectpage/model/admin?type=all" data-field="nickname" data-orderBy="id desc"',
),
array("field" => 'order_admin_id', "title" => '签约人', "addclass" => "selectpage", "formatter" => '(function (v, r) {
if (!r.order_admin) return \'-\';
return r.order_admin.nickname;
})',
"extend" => 'data-source="facrm/common/selectpage/model/admin?type=all" data-field="nickname" data-orderBy="id desc"',
),
array("field" => 'create_time', "title" => '创建时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'check_status', "title" => '状态', "formatter" => "Table.api.formatter.status", "searchList" => 'check_status'),
);
... ...
<?php
/**
* 客户自定义表排序
*/
return array(
array("field" => 'id', "title" => '客户ID', "sortable" => true),
array("field" => 'name', "title" => '客户名称', "operate" => "LIKE", "align" => 'left', 'customField' => 'tags', "class" => "tabletd",
"formatter" => '(function (value, row, index) {
value=\'<a href="javascript:void(0);" data-url="facrm/customer/record/add/ids/\' + row.id
+\'" data-area="[&quot;98%&quot;,&quot;98%&quot;]" class="btn-addtabs" data-toggle="tooltip" data-original-title="\'+ value+\'" data-title="\'+ value+\'">\'+ value+\'</a>\';
return value +
\'<div >\' + Table.api.formatter.flag.call(this, row[\'tags\'], row, index) + \'</div>\';
})',
"cellStyle" => '(function(value, row, index, field){return {css: {"max-width":"200px"}};})'),
array("field" => 'tags', "title" => '标签', "visible" => false, "formatter" => "Table.api.formatter.flag", "operate" => 'find_in_set'),
array("field" => 'telephone', "title" => '电话', "operate" => "LIKE"),
array("field" => 'mobile', "title" => '手机', "operate" => "LIKE"),
array("field" => 'owner_user_id', "title" => '负责人', "addclass" => "selectpage", "class" => "tabletd", "cellStyle" => "(function(value, row, index, field){
return {css: { \"max-width\":\"200px\"}};
})",
'formatter' => "(function (v, r) {
if (!r.owner_user) return '-';
return r.owner_user.nickname;})",
'extend' => 'data-source="facrm/common/selectpage/model/admin?type=children" data-field="nickname" data-orderBy="id desc"'
),
array("field" => 'deal_status', "title" => '成交状态', "formatter" => "Table.api.formatter.status", "searchList" => 'deal_status'),
array("field" => 'remark', "title" => '备注', "operate" => "LIKE", "class" => "tabletd", "align" => "left", "cellStyle" => "(function(value, row, index, field){
return {css: { \"max-width\":\"250px\"}};
})"),
array("field" => 'level', "title" => '客户级别', "formatter" => "Table.api.formatter.status", "searchList" => 'levelList'),
array("field" => 'industry', "title" => '行业', "formatter" => "(function (v, row, index) {
if(!v) return '无';
return industryList[v];
})", "searchList" => 'industryList'),
array("field" => 'source', "title" => '来源', "formatter" => "Table.api.formatter.status", "searchList" => 'sourceList'),
array("field" => 'create_user_id', "title" => '创建人', "addclass" => "selectpage", "formatter" => '(function (v, r) {
if (!r.create_user) return \'-\';
return r.create_user.nickname;
})',
"extend" => 'data-source="facrm/common/selectpage/model/admin?type=children" data-field="nickname" data-orderBy="id desc"',
),
array("field" => 'next_time', "title" => '下次跟进', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'follow_time', "title" => '最近跟进', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'create_time', "title" => '创建时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'collect_time', "title" => '领取时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
array("field" => 'update_time', "title" => '更新时间', "operate" => "RANGE", "sortable" => true, "formatter" => "Table.api.formatter.datetime", "addclass" => "datetimerange", "extend" => 'autocomplete="off" data-time-picker="true"'),
);
... ...
此 diff 太大无法显示。
<?php
namespace addons\facrm\controller;
use EasyWeChat\Factory;
use think\Config;
use think\Db;
use think\Queue;
/**
* 定时任务
* @internal
*/
class Autotask extends \think\addons\Controller
{
protected $noNeedLogin = ["*"];
protected $layout = '';
public function _initialize()
{
set_time_limit(0);
parent::_initialize();
if (!$this->request->isCli()) {
$this->error('只允许在终端进行操作!');
}
}
/**
* 定时任务逻辑
*/
public function index()
{
$this->flowcustomer();
$this->flowbusiness();
$this->expirecontract();
$this->expirecustomer();
$this->flowclues();
}
/**
* 待跟进客户提醒
*/
public function flowcustomer()
{
//当天开始时间
$start_time = strtotime(date("Y-m-d", time()));
//当天结束之间
$end_time = $start_time + 60 * 60 * 24;
$customerModel = model('\app\admin\model\facrm\Customer');
//需要联系客户
$communicate = $customerModel->where('next_time', 'between', [1, $end_time])
->field('COUNT(*) AS count,owner_user_id ')
->where('owner_user_id', "<>", '0')
->group('owner_user_id')
->select();
foreach ($communicate as $row) {
if ($row->count <= 0) continue;
//通知队列
Queue::push("addons\\facrm\\library\\notice\queue\\CustomerJob", [
'key' => 'notice_flow_customer',//待跟进通知模板
'admin_ids' => $row->owner_user_id,
'count' => $row->count,
]);
}
echo "done";
return;
}
/**
* 待跟进线索提醒
*/
public function flowclues()
{
//当天开始时间
$start_time = strtotime(date("Y-m-d", time()));
//当天结束之间
$end_time = $start_time + 60 * 60 * 24;
$cluesModel = model('\app\admin\model\facrm\Clues');
//需要联系线索
$communicate = $cluesModel->where('next_time', 'between', [1, $end_time])
->field('COUNT(*) AS count,owner_user_id ')
->where('owner_user_id', "<>", '0')
->group('owner_user_id')
->select();
foreach ($communicate as $row) {
if ($row->count <= 0) continue;
//通知队列
Queue::push("addons\\facrm\\library\\notice\queue\\CluesJob", [
'key' => 'notice_flow_clues',//待跟进通知模板
'admin_ids' => $row->owner_user_id,
'count' => $row->count,
]);
}
echo "done";
return;
}
/**
* 待跟进商机提醒
*/
public function flowbusiness()
{
//当天开始时间
$start_time = strtotime(date("Y-m-d", time()));
//当天结束之间
$end_time = $start_time + 60 * 60 * 24;
$thisModel = model('\app\admin\model\facrm\Business');
//需要联系
$communicate = $thisModel->where('next_time', 'between', [1, $end_time])
->where('is_end', 0)
->field('COUNT(*) AS count,owner_user_id ')
->where('owner_user_id', "<>", '0')
->group('owner_user_id')
->select();
foreach ($communicate as $row) {
if ($row->count <= 0) continue;
//通知队列
Queue::push("addons\\facrm\\library\\notice\queue\\BusinessrJob", [
'key' => 'notice_flow_business',//待跟进通知模板
'admin_ids' => $row->owner_user_id,
'count' => $row->count,
]);
}
echo "done";
return;
}
/**
* 将过期合同(提前三十天)
*/
public function expirecontract()
{
//当天开始时间
$start_time = strtotime(date("Y-m-d", time()));
//当天结束之间
$end_time = $start_time + 60 * 60 * 24;
$thisModel = model('\app\admin\model\facrm\Contract');
//需要联系
$communicate = $thisModel->where('end_time', 'between', [1, $end_time + (30 * 86400)])
->where('expire_handle', 0)
->field('COUNT(*) AS count,owner_user_id ')
->where('owner_user_id', "<>", '0')
->group('owner_user_id')
->select();
foreach ($communicate as $row) {
if ($row->count <= 0) continue;
//通知队列
Queue::push("addons\\facrm\\library\\notice\queue\\ContractJob", [
'key' => 'notice_expire_contract',//待跟进通知模板
'admin_ids' => $row->owner_user_id,
'count' => $row->count,
]);
}
echo "done";
return;
}
/**
* 将要过期客户提醒
*/
public function expirecustomer()
{
$config = get_addon_config('facrm');
//判断是否开启过期的功能
if ($config['lose_day1'] <= 0 && ($config['lose_day2'] <= 0)) {
echo "done none";
return;
}
$thisModel = model('\app\admin\model\facrm\Customer');
$lists = $thisModel->getLoseWhere($config, 1)
->field('COUNT(*) AS count,owner_user_id ')
->where('owner_user_id', "<>", '0')
->group('owner_user_id')
->select();
foreach ($lists as $row) {
if ($row->count <= 0) continue;
//通知队列
Queue::push("addons\\facrm\\library\\notice\queue\\CustomerJob", [
'key' => 'notice_expire_ccustomer',//客户将过期通知模板
'admin_ids' => $row->owner_user_id,
'count' => $row->count,
]);
}
echo "done";
return;
}
/**
* 云呼记录同步云呼建议1个小时执行一次【废弃已改用事件通知】
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function calllog()
{
$this->key = "cloudcall";
//获取云呼配置
$all_types = \addons\facrm\library\cloudcall\Call::getProviders();
$keys = "";
foreach ($all_types as $v) {
$keys .= $keys ? ',' . $this->key . $v : $this->key . $v;
}
$settingModel = new \app\admin\model\facrm\Setting();
$setting = $settingModel->where('key', 'in', $keys)->where('status', 1)->find();//只找一条云呼通道
if (!$setting) {
$this->error(__("云呼通道没有配置,请先配置"));
}
//获取坐席
$setting = $setting->toArray();
$setting['key'] = $setting['describe'];
$setting = array_merge($setting, $setting['values']);
$call = \addons\facrm\library\cloudcall\Call::instance($setting);
$calldata['beginTime'] = datetime(time() - (86400 * 1), 'Y-m-d H:i:s');//开始时间
$calldata['endTime'] = datetime(time(), 'Y-m-d H:i:s');//结束时间
$result = $call->getCallRecord($calldata);
if (!$result) {
$this->error($call->getError());
}
$result = json_decode($result, true);
if (isset($result['success']) && $result['success'] && $result['data']) {
$cloudcallLog = new \app\admin\model\facrm\CloudcallLog();
foreach ($result['data'] as $r) {
if (!$r['ACTION_ID']) continue;
$log = $cloudcallLog->where('action_id', $r['ACTION_ID'])->where('status', 0)->find();
if (!$log) continue;
$log->call_no = $r['CALL_NO'];
$log->status = $r['STATUS'] == 'dealing' ? 1 : -1;
$log->record_file = $r['FILE_SERVER'] . '/' . $r['RECORD_FILE_NAME'];
$log->call_time_length = $r['CALL_TIME_LENGTH'];
$log->save();
}
}
}
/**
* 同步微信员工、客户
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @throws \think\exception\PDOException
*/
public function synwx()
{
set_time_limit(0);
$key = "work_weixin_set";
$settingModel = new \app\admin\model\facrm\Setting();
$row = $settingModel->where('key', $key)->cache(1800)->find();
if (!$row) {
echo "企业微信未配置";
return;
}
$values = json_decode($row['values'], true);//获取器不知道为什么失效了
if (!$values) {
echo "企业微信未配置1";
return;
}
$config = [
'corp_id' => $values['corp_id'],
'secret' => $values['agent_secret'],
'agent_id' => $values['agent_id'],
//'agent_secret' => $values['agent_secret'],
];
try {
$app = Factory::work($config);
$result = $app->user->getDetailedDepartmentUsers(1, true);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
if (!$result || $result['errcode'] != '0') {
$errmsg = isset($result['errmsg']) ? $result['errmsg'] : 'null';
echo "获取失败:" . $errmsg;
return;
}
$userlist = $result['userlist'];
$result = 0;
foreach ($userlist as $user) {
//判断系统是否存在
$qywxUser = \app\admin\model\facrm\qywx\User::getUser($user['userid'], $values, $user);
if ($qywxUser) $result++;
}
echo "同步更新企业微信员工{$result}条";
/*-----------同步员工end----------------*/
$this->synwxcustomer($values);
return;
}
protected function synwxcustomer($values,$page=1,$next_cursor="",$is_action=true){
$c_config = [
'corp_id' => $values['corp_id'],
'secret' => $values['customer_secret'], // 客户的 secret
];
$appc = Factory::work($c_config);
$qywxUserModel = new \app\admin\model\facrm\qywx\User();
$userList = $qywxUserModel->page($page,100)->order('id asc')->column('admin_id','userid');
if (!$userList){
echo "同步客户完成";
return;
}
$contactsModel = new \app\admin\model\facrm\qywx\Contacts();
$externalcontact = new \addons\facrm\library\extend\easywechat\Externalcontact($appc);
try {
//批量查询客户详情
$externalList = $externalcontact->batch(array_keys($userList),$next_cursor,100);
} catch (\Exception $e) {
echo $e->getMessage();
}
if (!$externalList || $externalList['errcode'] != '0' ){
echo $externalList['errmsg'];
}
if ($externalList['external_contact_list']&&count($externalList['external_contact_list'])>0){
$syn_number=count($externalList['external_contact_list']);
foreach ($externalList['external_contact_list'] as $row) {
$follow_user = $row['follow_info'];
$admin_id=isset($userList[$follow_user['userid']])?$userList[$follow_user['userid']]:0;
$contactsModel->getContacts($row, $values, ['admin_id' => $admin_id]);
}
if (isset($externalList['next_cursor'])&&$externalList['next_cursor']){
$syn_number+=$this->synwxcustomer($values,$page,$externalList['next_cursor'],false);
}
}
if (!$is_action){
return $syn_number;
}
echo "本次同步更新{$syn_number}条客户数据";
return $this->synwxcustomer($values,$page+1);
}
}
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace addons\facrm\controller;
use addons\facrm\library\BackendApi;
use think\Config;
use think\captcha\Captcha as CaptchaLib;
/**
* 图片验证码
* Class Captcha
* @package addons\facrm\controller
*/
class Captcha extends BackendApi
{
protected $noNeedLogin = ['index'];
public function index()
{
$id=request()->param('id');
$sid=request()->param('sid');
if (!$sid){
session_start();
session_id();
$this->success('',session_id());
}else{
session_id($sid);
session_start();
}
$captcha = new CaptchaLib((array)Config::get('captcha'));
return $captcha->entry($id);
}
}
\ No newline at end of file
... ...
<?php
namespace addons\facrm\controller;
use fast\Date;
use think\addons\Controller;
/**
* 云呼回调接口
* @icon fa fa-circle-o
*/
class Cloudcall extends Controller
{
protected $cacheCallName = "cache_call_engine_name";
protected $calltypes = [];
public function _initialize()
{
parent::_initialize();
$this->request->filter(['strip_tags']);
}
/**
* 通话记录回调
* @ApiParams(name="engine", type="string", required=true, description="通道")
* @ApiBody ("域名/addons/facrm/cloudcall/back?engine=通道(如Tycc100)")
* @ApidBody
*/
public function back($engine=null)
{
$engine=!$engine?$this->request->request('engine'):$engine;
$engine=!$engine?$this->request->route('engine'):"";
if (!$engine){
$this->error("通道不存在");
}
$this->setting = cache($this->cacheCallName.$engine);
if (!$this->setting) {
$this->key = "cloudcall";
$settingModel = new \app\admin\model\facrm\Setting();
$this->setting=$settingModel->where('key', "cloudcall".$engine)->find();
if (!$this->setting){
$this->error("通道不存在");
}
$this->setting=$this->setting->toArray();
cache($this->cacheCallName.$engine, $this->setting, 86400);//缓存一天
}
$this->setting['key'] = $this->setting['describe'];
$this->setting = array_merge($this->setting, $this->setting['values']);
$call= \addons\facrm\library\cloudcall\Call::instance($this->setting);
$result=$call->back();
}
}
... ...
<?php
namespace addons\facrm\controller;
use addons\facrm\library\BackendApi;
use addons\facrm\model\Admin as AdminModel;
use app\admin\model\AdminLog;
use think\Config;
use think\Hook;
use think\Validate;
/**
* 登录操作
* @internal
*/
class Index extends BackendApi
{
protected $noNeedLogin = ['login', 'wxlogin','bind','mplogin'];
protected $noNeedRight = ['logout','unbind','thirdlist'];
protected $platforms =['admin_min','admin_mp'] ;//admin_min微信小程序登录标识
public function _initialize()
{
parent::_initialize();
//移除HTML标签
$this->request->filter('trim,strip_tags,htmlspecialchars');
}
/**
* 登录[帐号和密码]
* @ApiMethod (post)
* @ApiParams(name="username", type="string", required=true, description="帐号")
* @ApiParams(name="password", type="string", required=true, description="密码")
* @ApiParams(name="keeplogin", type="string", required=false, description="保持登录,暂时未做")
*/
public function login()
{
$username = $this->request->post('username');
$password = $this->request->post('password');
$keeplogin = $this->request->post('keeplogin');
$sid=$this->request->post('sid');
if ($sid){
session_id($sid);
session_start();
}
$rule = [
'username' => 'require|length:3,30',
'password' => 'require|length:3,30',
];
$data = [
'username' => $username,
'password' => $password,
];
if (Config::get('fastadmin.login_captcha')) {
$rule['captcha'] = 'require|captcha';
$data['captcha'] = $this->request->post('captcha');
}
$validate = new Validate($rule, [], ['username' => __('Username'), 'password' => __('Password'), 'captcha' => __('Captcha')]);
$result = $validate->check($data);
if (!$result) {
$this->error($validate->getError());
}
AdminLog::setTitle(__('移动端帐号登录'));
$result = $this->auth->login($username, $password, $keeplogin ? 86400 : 0);
if ($result === true) {
$admin = $this->auth->getAdmin();
if ($admin) {
Hook::listen("admin_login_after", $this->request);
$this->success(__("登录成功!"), [
'token' => $admin->token,
'id' => $admin->id,
'username' => $admin->username,
'nickname' => $admin->nickname,
'avatar' => cdnurl($admin->avatar, true),
]);
}
}
$msg = $this->auth->getError();
$msg = $msg ? $msg : __('Username or password is incorrect');
$this->error($msg);
}
/**
* 小程序微信登录
* @ApiMethod (post)
* @ApiParams(name="code", type="string", required=true, description="code")
* @ApiParams(name="encrypted_data", type="string", required=true, description="encrypted_data")
* @ApiParams(name="iv", type="string", required=true, description="iv")
*/
public function wxlogin()
{
$platform='admin_min';
$model = new AdminModel();
$post = $this->request->post();
$third = get_addon_info('third');
if (!$third || $third['state']!=1) {
$this->error(__("请先安装第三方登录插件"));
}
$data = $model->minLogin($post);
if (!$data) {
$this->error($model->getError());
}
$data['openid'] = $data['openId'];
$data['unionId'] =isset($data['unionId'])? $data['unionId']:'';
$data['access_token'] = $data['refresh_token'] = $post['code'];
$data['expires_in'] = 0;
$data['userinfo']['nickname'] = $data['nickName'];
$data['userinfo']['avatar'] = $data['avatarUrl'];
$third = $model->connects($platform, $data);
AdminLog::setTitle(__('小程序登录'));
if ($third) {
if (isset($third->user_id)&&$third->user_id) {
$admin = $this->auth->direct($third->user_id);
if ($admin) {
Hook::listen("admin_login_after", $this->request);
$this->success(__("登录成功!"), [
'token' => $admin->token,
'id' => $admin->id,
'username' => $admin->username,
'nickname' => $admin->nickname,
'avatar' => cdnurl($admin->avatar, true),
]);
}
$this->error(__($this->auth->getError()));
} else {
//绑定帐号
$this->error(__("跳转到绑定帐号"), ['refresh_token' => $third->refresh_token]);
}
}
$this->error(__("登录失败,请重试"));
}
/**
* 微信公众号登录
* @ApiMethod (get)
* @ApiParams(name="code", type="string", required=true, description="code")
*/
public function mplogin(){
$platform='admin_mp';
$model = new AdminModel();
$get = $this->request->get();
$third = get_addon_info('third');
if (!$third || $third['state']!=1) {
$this->error(__("请先安装第三方登录插件"));
}
$data = $model->mpLogin($get);
if (!$data) {
$this->error($model->getError());
}
if (!isset($data['original']['openid'])){
$this->error(__("获取微信登录信息失败"));
}
$data_param['openid'] = $data['original']['openid'];
$data_param['unionId'] =isset($data['original']['unionId'])? $data['original']['unionId']:'';
$data_param['expires_in'] =3600;
$data_param['userinfo']['nickname'] = $data['nickname'];
$data_param['userinfo']['avatar'] = $data['avatar'];
$data_param['access_token'] = $data['access_token'];
$data_param['refresh_token'] = $data['refresh_token'];
$third = $model->connects($platform, $data_param);
AdminLog::setTitle(__('公众号登录'));
if ($third) {
if (isset($third->user_id)&&$third->user_id) {
$admin = $this->auth->direct($third->user_id);
if ($admin) {
Hook::listen("admin_login_after", $this->request);
$this->success(__("登录成功!"), [
'token' => $admin->token,
'id' => $admin->id,
'username' => $admin->username,
'nickname' => $admin->nickname,
'avatar' => cdnurl($admin->avatar, true),
]);
}
$this->error(__($this->auth->getError()));
} else {
//绑定帐号
$this->error(__("跳转到绑定帐号"), ['refresh_token' => $third->refresh_token]);
}
}
$this->error(__("登录失败,请重试"));
}
/**
* 绑定原有帐号
* @ApiMethod (POST)
* @ApiParams(name="username", type="string", required=true, description="帐号")
* @ApiParams(name="password", type="string", required=true, description="密码")
* @ApiParams(name="keeplogin", type="string", required=false, description="保持登录,暂时未做")
* @ApiParams(name="platform", type="string", required=false, description="绑定平台admin_min:小程序 admin_mp:公众号")
* @ApiParams (name="refresh_token", type="string", required=true, sample="",description="绑定凭证")
* @ApiReturnParams (name="token", type="string", required=false, sample="0",description="登录凭证")
* admin_mp
* @return array
*/
public function bind()
{
$platform = $this->request->post('platform','admin_min');
$refresh_token = $this->request->post('refresh_token');
$username = $this->request->post('username');
$password = $this->request->post('password');
$keeplogin = $this->request->post('keeplogin');
$sid=$this->request->post('sid');
if ($sid){
session_id($sid);
session_start();
}
if (!$refresh_token) {
$this->error("获取登录信息错误");
}
$rule = [
'username' => 'require|length:3,30',
'password' => 'require|length:3,30',
];
$data = [
'username' => $username,
'password' => $password,
];
if (Config::get('fastadmin.login_captcha')) {
$rule['captcha'] = 'require|captcha';
$data['captcha'] = $this->request->post('captcha');
}
$validate = new Validate($rule, [], ['username' => __('用户名'), 'password' => __('密码'), 'captcha' => __('验证码')]);
$result = $validate->check($data);
if (!$result) {
$this->error($validate->getError());
}
$third = \addons\third\model\Third::where('refresh_token', $refresh_token)->where('platform', $platform)->find();
if (!$third) {
$this->error(__('绑定的数据不存在'));
}
if ($third->user_id > 0) {
$this->error(__('已绑定过'));
}
if ($third['updatetime'] < (time() - 1800)) {
$third->delete();
$this->error(__('请求已经过期,请重试!'));
}
AdminLog::setTitle(__('小程序绑定登录'));
$result = $this->auth->login($username, $password, $keeplogin ? 86400 : 0);
if ($result === true) {
$admin = $this->auth->getAdmin();
if ($admin) {
Hook::listen("admin_login_after", $this->request);
$third['user_id'] = $admin->id;
$third->save();
$this->success(__("登录成功!"), [
'token' => $admin->token,
'id' => $admin->id,
'username' => $admin->username,
'nickname' => $admin->nickname,
'avatar' => cdnurl($admin->avatar, true),
]);
}
}
$msg = $this->auth->getError();
$msg = $msg ? $msg : __('Username or password is incorrect');
$this->error($msg);
}
/**
* 解绑
*@ApiParams(name="platform", type="string", required=true, description="平台:admin_min:小程序 admin_mp:公众号")
*/
public function unbind(){
$platform = $this->request->post('platform','admin_min');
if (!in_array($platform,$this->platforms)){
$this->error(__('平台不存在'));
}
$third = \addons\third\model\Third::where('user_id', $this->auth->id)->where('platform', $platform)->find();
if (!$third) {
$this->error(__('绑定的数据不存在'));
}
$third->delete();
$this->success(__("解绑成功!"));
}
/**
* 获取第三方登录绑定列表
*/
public function thirdlist(){
$third = get_addon_info('third');
if (!$third || $third['state']!=1) {
$this->error(__("请先安装第三方登录插件"));
}
$thirdlist = \addons\third\model\Third::where('user_id', $this->auth->id)
->field('id,platform,openname,logintime')
->where('platform', 'in',$this->platforms)->select();
$this->success('',$thirdlist);
}
/**
* 退出登录
*/
public function logout()
{
$this->auth->logout();
$this->success(__("退出成功"));
}
}
... ...
<?php
namespace addons\facrm\controller;
use addons\third\model\Third;
use fast\Date;
use think\addons\Controller;
use think\Exception;
use think\Response;
/**
* 订单支付
* @icon fa fa-circle-o
*/
class Order extends Controller
{
protected $layout = 'default';
protected $pay_config = [];
protected $key = "payonline";
public function _initialize()
{
parent::_initialize();
$epayinfo = get_addon_info('epay');
if (!$epayinfo || !$epayinfo['state']){
$this->error(__("微信支付宝插件未安装或未启用"));
}
$this->view->assign("epayinfo", $epayinfo);
$this->request->filter(['strip_tags']);
$settingModel = new \app\admin\model\facrm\Setting();
$this->pay_config =\addons\facrm\library\Order::getPayConfig();
if (!$this->pay_config) {
$this->error(__("未配置收款"));
}
}
/**
* 支付订单[收款]
*/
public function pay()
{
if (!$this->pay_config['values']['online_pay']) {
$this->error(__("未配置收款"));
}
//获取收款单信息
$pay_token = $this->request->request('pay_token');//访问凭证
if (!$pay_token) {
$this->error(__("访问有误"));
}
$receivablesModel = new \app\admin\model\facrm\contract\Receivables();
$payInfo = $receivablesModel->where('pay_token', $pay_token)->find();
$tempvars=$payInfo->toArray();
$check_data=\addons\facrm\library\Order::checkPay($payInfo, 'pay',$this->pay_config);
if ($check_data['code']!=1){
$this->error(__($check_data['msg']));
}
$agreement = __($this->pay_config['values']['agreement'],$tempvars);
$this->view->assign("row", $payInfo);
$this->view->assign("agreement", $agreement);
$this->view->assign("title", __("支付订单"));
return $this->view->fetch();
}
/**
* 合同续费
*/
public function renew()
{
//获取合同信息
$pay_token = $this->request->request('pay_token');
if (!$pay_token) {
$this->error(__("访问有误"));
}
//判断是否开启续费功能
if ($this->pay_config['values']['renew_pay'] != 1) {
$this->error(__("未开启续费功能"));
}
$contractModel = new \app\admin\model\facrm\Contract();
$contractInfo = $contractModel->where('renewtoken', $pay_token)->find();
$check_data=\addons\facrm\library\Order::checkPay($contractInfo, 'renew',$this->pay_config);
if ($check_data['code']!=1){
$this->error(__($check_data['msg']));
}
//判断合同是否设定了续费单价,
if ($contractInfo['renewmoeny']<=0){
$contractInfo['renewmoeny']=bcdiv(($contractInfo['money']*$this->pay_config['values']['renew_percentage']),100,2);
}
$pay_config=$this->pay_config['values'];
$pay_config['r_agreement'] = __($pay_config['r_agreement'], $contractInfo->toArray());
$this->view->assign("pay_config", $pay_config);
$this->view->assign("row", $contractInfo);
$this->view->assign("title", __("续费"));
return $this->view->fetch();
}
/**
* 提交支付订单
* @return \addons\epay\library\Collection|\addons\epay\library\RedirectResponse|\addons\epay\library\Response
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function submit()
{
$pay_token = request()->request('pay_token');
if (!$pay_token) $this->error("付款单不存在");
$info = get_addon_info('epay');
if (!$info || !$info['state']) {
$this->error('请在后台插件管理安装微信支付宝整合插件后重试');
}
$paytype = $this->request->request('paytype', 'wechat');
$ordertype = $this->request->request('ordertype', 'pay');
$method = $this->request->request('method');
$appid = $this->request->request('appid');//APP的应用ID
$returnurl = $this->request->request('returnurl', '', 'trim');
$number = $this->request->request('number', '1', 'intval');//下单数量,只有续费才有效果
//公众号和小程序
$openid = '';
if (in_array($method, ['miniapp', 'mp'])) {
$third = Third::where('platform', 'wechat')->where('apptype', $method)->where('user_id', $this->auth->id)->find();
if (!$third) {
$this->error("未找到登录用户信息", 'bind');
}
$openid = $third['openid'];
}
try {
$response = \addons\facrm\library\Order::submit($pay_token, $ordertype,$paytype, $method, $openid, $appid, $returnurl, ['number' => $number]);
return $response;
} catch (\Exception $e) {
$this->error($e->getMessage());
}
}
/**
* 企业支付通知和回调
*/
public function epay()
{
\think\Log::write(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '_________', 'error');
$type = $this->request->param('type');
$paytype = $this->request->param('paytype');
if ($type == 'notify') {
\think\Log::write('__验证开始__', 'error');
$pay = \addons\epay\library\Service::checkNotify($paytype);
if (!$pay) {
\think\Log::write('__签名错误_', 'error');
echo '签名错误';
return;
}
$data = $pay->verify();
/* //调试
$data=array(
'total_amount'=>800,
'out_trade_no'=>'20220519113008000000003943',
'total_fee'=>80000,
);*/
try {
$payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
\think\Log::write('__进入支付_', 'error');
\addons\facrm\library\Order::settle($data['out_trade_no'], $payamount);
} catch (Exception $e) {
\think\Log::write($e->getMessage() . '__支付异常报错_', 'error');
}
echo $pay->success();
} else {
$pay = \addons\epay\library\Service::checkReturn($paytype);
if (!$pay) {
$this->error('签名错误');
}
//微信支付没有返回链接
if ($pay === true) {
$this->success("请返回网站查看支付状态!", "");
}
//你可以在这里定义你的提示信息,但切记不可在此编写逻辑
$this->success("请返回网站查看支付状态!", url("user/index"));
}
return;
}
/**
* 生成二维码
*/
public function qrcode()
{
$text = $this->request->get('text', 'hello world');
//如果有安装二维码插件,则调用插件的生成方法
if (class_exists("\addons\qrcode\library\Service") && get_addon_info('qrcode')['state']) {
$qrCode = \addons\qrcode\library\Service::qrcode(['text' => $text]);
$response = Response::create()->header("Content-Type", "image/png");
header('Content-Type: ' . $qrCode->getContentType());
$response->content($qrCode->writeString());
return $response;
} else {
$qr = \addons\facrm\library\QRCode::getMinimumQRCode($text);
$im = $qr->createImage(8, 5);
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
return;
}
}
}
... ...
<?php
namespace addons\facrm\controller;
use app\admin\model\Admin;
use EasyWeChat\Factory;
use think\addons\Controller;
use think\Hook;
use think\Log;
use think\Session;
use app\admin\model\facrm\qywx\User as QywxUser;
use EasyWeChat\Kernel\Support;
use addons\facrm\library\BackendApi;
/**
* 企业微信通信管理
* @icon fa fa-circle-o
*/
class Qywx extends BackendApi
{
protected $app = null;//EasyWeChat 实列
protected $config = array();//企业微信配置
protected $noNeedRight = ['*'];
protected $noNeedLogin = ['connect','login','wxlogin'];
public function _initialize()
{
//跨域请求检测
check_cors_request();
parent::_initialize();
$this->request->filter(['strip_tags']);
$key = "work_weixin_set";
$settingModel = new \app\admin\model\facrm\Setting();
$row = $settingModel->where('key', $key)->find();
if (!$row) $this->error(__("企业微信未配置"));
$this->config = json_decode($row['values'], true);//获取器不知道为什么失效了
if (!$this->config) $this->error(__("企业微信未配置1"));
}
/**
* 微信验证
* @ApiInternal
*/
public function connect()
{
$config = [
'corp_id' => $this->config['corp_id'],
'agent_id' => $this->config['agent_id'],
'secret' => $this->config['agent_secret'],
'token' => $this->config['customer_callback_token'],
'aes_key' => $this->config['EncodongAESKey'],
];
$app = Factory::work($config);
$app->server->push(function($message){
$res= \addons\facrm\library\qywx\Event::execute($message);
});
$response = $app->server->serve();
$response->send();
}
/**
* 企业微信H5登录
* @ApiParams(name="code", type="string", required=true, description="post请求的时候需要")
* @ApiParams(name="url", type="string", required=true, description="url")
* @ApiBody ("get是获取一些基本配置")
*
*/
public function login(){
$app_ag_config = [
'corp_id' => $this->config['corp_id'],
'agent_id' => $this->config['agent_id'],
'secret' => $this->config['agent_secret'],
];
if (request()->isGet()){
$url = $this->request->param('url');
$config = [
'corp_id' => $this->config['corp_id'],
'agent_id' => $this->config['agent_id'],
'secret' => $this->config['customer_secret'],
];
$this->app = $app = Factory::work($config);
$wx_config = ($app->jssdk->buildConfig(['updateAppMessageShareData', 'updateTimelineShareData'], $debug = false, $beta = false, $json = true, $openTagList = []));
$this->app = $app = Factory::work($app_ag_config);
$supportExtend=new \addons\facrm\library\extend\easywechat\SupportExtend($app);
$ag_config = $supportExtend->buildAgentConfig(
['getCurExternalContact'],
$this->config['agent_id'],
$debug = false,
$beta = false,
$json = true,
$openTagList = [],
$url
);
$this->success('',['wx_config'=>json_decode($wx_config,true),'ag_config'=>json_decode($ag_config,true)]);
}else{
$app = Factory::work($app_ag_config);
$user = $app->oauth->detailed()->user();
// 获取用户信息
$userid = $user->getId(); // 对应企业微信英文名(userid)
if (!$userid) $this->error(__("获取企业微信信息失败"));
$loca_user = QywxUser::getUser($userid);
if (!$loca_user) {
//不存在就调用接口去获取
$c_config = [
'corp_id' => $this->config['corp_id'],
'secret' => $this->config['contacts_secret'], // 通讯录的 secret
];
$contacts = Factory::work($c_config);
$qywx_user = $contacts->user->get($userid);
if (!$qywx_user || $qywx_user['errcode'] != '0') $this->error(__("获取企业微信信息失败"));
$loca_user = QywxUser::getUser($userid, $this->config, $qywx_user);
}
if (!$loca_user || !$loca_user['admin_id']) {
$this->error(__("企业微信登录失败"));
}
$admin = $this->auth->direct($loca_user['admin_id']);
if ($admin) {
Hook::listen("admin_login_after", $this->request);
$this->success(__("登录成功!"), [
'token' => $admin->token,
'id' => $admin->id,
'username' => $admin->username,
'nickname' => $admin->nickname,
'avatar' => cdnurl($admin->avatar, true),
]);
}
$this->error(__($this->auth->getError()));
}
$this->error(__('登录失败'));
}
/**
* 企业微信小程序登录
* @ApiBody ("")
*
*/
public function wxlogin(){
$config = [
'corp_id' => $this->config['corp_id'],
'agent_id' => $this->config['agent_id'],
'secret' => $this->config['agent_secret'],
];
$app = Factory::work($config);
$miniProgram = $app->miniProgram();
$res = $miniProgram->auth->session("js-code");
if ($res&&isset($res['userid'])){
$userid = $res['userid']; // 对应企业微信英文名(userid)
if (!$userid) $this->error(__("获取企业微信信息失败"));
$loca_user = QywxUser::getUser($userid);
if (!$loca_user) {
//不存在就调用接口去获取
$c_config = [
'corp_id' => $this->config['corp_id'],
'secret' => $this->config['contacts_secret'], // 通讯录的 secret
];
$contacts = Factory::work($c_config);
$qywx_user = $contacts->user->get($userid);
if (!$qywx_user || $qywx_user['errcode'] != '0') $this->error(__("获取企业微信信息失败"));
$loca_user = QywxUser::getUser($userid, $this->config, $qywx_user);
}
if (!$loca_user || !$loca_user['admin_id']) {
$this->error(__("企业微信登录失败"));
}
$admin = $this->auth->direct($loca_user['admin_id']);
if ($admin) {
Hook::listen("admin_login_after", $this->request);
$this->success(__("登录成功!"), [
'token' => $admin->token,
'id' => $admin->id,
'username' => $admin->username,
'nickname' => $admin->nickname,
'avatar' => cdnurl($admin->avatar, true),
]);
}
$this->error(__($this->auth->getError()));
}
$this->error(__("获取企业微信信息失败2"));
}
/**
* 获取客户ID
* @ApiParams(name="userid", type="string", required=true, description="企业微信客户")
* @ApiBody ("get是获取一些基本配置")
* @Internal
*/
public function getCustomerId()
{
$admin = $this->auth->getUserInfo();
if (!$admin) $this->error(__("未登录"));
$external_userid = $this->request->param('userid');
if (!$external_userid) $this->error(__("userid不能为空"));
//获取本地微信外部联系人customer_id;
$contactsModel = new \app\admin\model\facrm\qywx\Contacts();
$qywxContacts = $contactsModel->getContacts($external_userid, $this->config, ['admin_id' => $admin['id']]);
if (!$qywxContacts) {
$this->error(__("获取企业客户信息失败"));
}
$this->success('', $qywxContacts->customer_id);
}
}
... ...
<?php
namespace addons\facrm\controller\auth;
use addons\facrm\library\BackendApi;
use app\admin\model\AuthGroup;
use app\admin\model\AuthGroupAccess;
use fast\Random;
use fast\Tree;
use think\Validate;
/**
* 管理员管理
*
* @icon fa fa-users
* @remark 一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成
*/
class Admin extends BackendApi
{
/**
* @var \app\admin\model\Admin
*/
protected $model = null;
protected $selectpageFields = 'id,username,nickname,avatar';
protected $searchFields = 'id,username,nickname';
protected $childrenGroupIds = [];
protected $childrenAdminIds = [];
protected $groupdata=[];
protected $noNeedRight = ['getGroupdata'];
public function _initialize()
{
parent::_initialize();
$this->model = model('\app\admin\model\Admin');
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
$this->childrenGroupIds = $this->auth->getChildrenGroupIds(true);
$groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray();
Tree::instance()->init($groupList);
if ($this->auth->isSuperAdmin()) {
$result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
foreach ($result as $k => $v) {
$this->groupdata[$v['id']] = $v['name'];
}
} else {
$result = [];
$groups = $this->auth->getGroups();
foreach ($groups as $m => $n) {
$result[$n['id']] =__($n['name']);
$childlist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['id']));
foreach ($childlist as $k => $v) {
$result[$v['id']] = $v['name'];
}
}
$this->groupdata = $result;
}
}
/**
* 查看
*/
public function index()
{
//设置过滤方法
$this->request->filter(['strip_tags', 'trim']);
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
$childrenGroupIds = $this->childrenGroupIds;
$groupName = AuthGroup::where('id', 'in', $childrenGroupIds)
->column('id,name');
$authGroupList = AuthGroupAccess::where('group_id', 'in', $childrenGroupIds)
->field('uid,group_id')
->select();
$adminGroupName = [];
foreach ($authGroupList as $k => $v) {
if (isset($groupName[$v['group_id']])) {
$adminGroupName[$v['uid']][$v['group_id']] = $groupName[$v['group_id']];
}
}
$groups = $this->auth->getGroups();
foreach ($groups as $m => $n) {
$adminGroupName[$this->auth->id][$n['id']] = $n['name'];
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$list = $this->model
->where($where)
->where('id', 'in', $this->childrenAdminIds)
->field(['password', 'salt', 'token'], true)
->order($sort, $order)
->paginate($limit);
foreach ($list as $k => &$v) {
$groups = isset($adminGroupName[$v['id']]) ? $adminGroupName[$v['id']] : [];
$v['groups'] = implode(',', array_keys($groups));
$v['groups_text'] = implode(',', array_values($groups));
}
unset($v);
$result = array("rows" => $list);
$this->success('', $result);
}
/**
* 获取员工组
*/
public function getGroupdata()
{
$this->success('',$this->groupdata);
}
/**
* 添加
*/
public function add()
{
if ($this->request->isPost()) {
$params = $this->request->post();
if ($params) {
if (!Validate::is($params['password'], '\S{6,16}')) {
$this->error(__("Please input correct password"));
}
$params['salt'] = Random::alnum();
$params['password'] = md5(md5($params['password']) . $params['salt']);
$params['avatar'] = '/assets/img/avatar.png'; //设置新管理员默认头像。
$result = $this->model->validate('\app\admin\validate\Admin.add')->allowField(true)->save($params);
if ($result === false) {
$this->error($this->model->getError());
}
$group = $this->request->post("group/a");
//过滤不允许的组别,避免越权
$group = array_intersect($this->childrenGroupIds, $group);
$dataset = [];
foreach ($group as $value) {
$dataset[] = ['uid' => $this->model->id, 'group_id' => $value];
}
model('\app\admin\model\AuthGroupAccess')->saveAll($dataset);
$this->success();
}
}
$this->error();
}
/**
* 编辑
* @ApiParams(name="id", type="int", required=true, description="管理员id")
* @ApiBody("get获取,post提交修改")
*/
public function edit()
{
$ids = $this->request->request('id', '', 'intval');
if (!$ids) {
$this->error(__('No Results were found'));
}
$row = $this->model->get(['id' => $ids]);
if (!$row) {
$this->error(__('No Results were found'));
}
if (!in_array($row->id, $this->childrenAdminIds)) {
$this->error(__('You have no permission'));
}
if ($this->request->isPost()) {
$params = $this->request->post();
if ($params) {
if ($params['password']) {
if (!Validate::is($params['password'], '\S{6,16}')) {
$this->error(__("Please input correct password"));
}
$params['salt'] = Random::alnum();
$params['password'] = md5(md5($params['password']) . $params['salt']);
} else {
unset($params['password'], $params['salt']);
}
//这里需要针对username和email做唯一验证
$adminValidate = \think\Loader::validate('\app\admin\validate\Admin');
$adminValidate->rule([
'username' => 'require|regex:\w{3,12}|unique:admin,username,' . $row->id,
'email' => 'require|email|unique:admin,email,' . $row->id,
'password' => 'regex:\S{32}',
]);
$result = $row->validate('\app\admin\validate\Admin.edit')->allowField(true)->save($params);
if ($result === false) {
$this->error($row->getError());
}
// 先移除所有权限
model('\app\admin\model\AuthGroupAccess')->where('uid', $row->id)->delete();
$group = $this->request->post("group/a");
// 过滤不允许的组别,避免越权
$group = array_intersect($this->childrenGroupIds, $group);
$dataset = [];
foreach ($group as $value) {
$dataset[] = ['uid' => $row->id, 'group_id' => $value];
}
model('\app\admin\model\AuthGroupAccess')->saveAll($dataset);
$this->success();
}
$this->error();
}
$grouplist = $this->auth->getGroups($row['id']);
$groupids = [];
foreach ($grouplist as $k => $v) {
$groupids[] = $v['id'];
}
$this->success('',['row'=>$row,'groupids'=>$groupids]);
}
/**
* 删除
* @ApiParams(name="ids", type="int", required=true, description="管理员id")
*/
public function del()
{
$ids = $this->request->request('ids', '', 'intval');
if (!$ids) {
$this->error(__('No Results were found'));
}
if (!$this->request->isPost()) {
$this->error(__("Invalid parameters"));
}
$ids = $ids ? $ids : $this->request->post("ids");
if ($ids) {
$ids = array_intersect($this->childrenAdminIds, array_filter(explode(',', $ids)));
// 避免越权删除管理员
$childrenGroupIds = $this->childrenGroupIds;
$adminList = $this->model->where('id', 'in', $ids)->where('id', 'in', function ($query) use ($childrenGroupIds) {
$query->name('auth_group_access')->where('group_id', 'in', $childrenGroupIds)->field('uid');
})->select();
if ($adminList) {
$deleteIds = [];
foreach ($adminList as $k => $v) {
$deleteIds[] = $v->id;
}
$deleteIds = array_values(array_diff($deleteIds, [$this->auth->id]));
if ($deleteIds) {
$this->model->destroy($deleteIds);
model('\app\admin\model\AuthGroupAccess')->where('uid', 'in', $deleteIds)->delete();
$this->success();
}
}
}
$this->error(__('You have no permission'));
}
/**
* 下拉搜索
*/
public function selectpage()
{
$this->dataLimit = 'auth';
$this->dataLimitField = 'id';
return parent::selectpage();
}
}
... ...
<?php
namespace addons\facrm\controller\facrm;
use app\admin\model\AuthGroup;
use addons\facrm\library\BackendApi;
use fast\Tree;
use think\Db;
use think\Exception;
/**
* 业绩目标
*
*/
class Achievement extends BackendApi
{
/**
* @var \app\admin\model\AuthGroup
*/
protected $model = null;
//当前登录管理员所有子组别
protected $childrenGroupIds = [];
protected $childrenAdminIds = [];
//当前组别列表数据
protected $groupdata = [];
protected $groupList = [];
//无需要权限判断的方法
protected $noNeedRight = ['roletree'];
public function _initialize()
{
parent::_initialize();
$this->request->filter(['strip_tags']);
$this->model = new AuthGroup();
$this->childrenGroupIds = $this->auth->getChildrenGroupIds(true);
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
$this->groupList = $groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray();
Tree::instance()->init($groupList);
$result = [];
if ($this->auth->isSuperAdmin()) {
$result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
} else {
$groups = $this->auth->getGroups();
foreach ($groups as $m => $n) {
$result = array_merge($result, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['pid'])));
}
}
$groupName = [];
foreach ($result as $k => $v) {
$groupName[$v['id']] = $v['name'];
}
$this->groupdata = $groupName;
}
protected $temp_achievement = [
'type' => 2,
'type_id' => '',
'year' => '',
'january' => '',
'february' => '',
'march' => '',
'april' => '',
'may' => '',
'june' => '',
'july' => '',
'august' => '',
'september' => '',
'october' => '',
'november' => '',
'december' => '',
'yeartarget' => '',
];
/**
* 查看列表
* @ApiMethod (get)
*/
public function index()
{
$achievement = new \app\admin\model\facrm\Achievement();
$filter = $this->request->get("filter", '');
$filter = (array)json_decode($filter, true);
$filter_w = [];
if (isset($filter['search_time'])) {
$filter_w['year'] = $filter['search_time'];
unset($filter['search_time']);
} else {
$filter_w['year'] = date('Y', time());
}
if (isset($filter['config'])) {
$filter_w['config'] = $filter['config'];
unset($filter['config']);
} else {
$filter_w['config'] = 1;
}
$this->request->get(['filter' => json_encode($filter)]);
if (isset($filter['group_id'])) {
$list = AuthGroup::all($filter['group_id']);
} else {
$list = AuthGroup::all(array_keys($this->groupdata));
}
$list = collection($list)->toArray();
$groupList = [];
foreach ($list as $k => $v) {
$groupList[$v['id']] = $v;
}
$list = [];
foreach ($this->groupdata as $k => $v) {
if (isset($groupList[$k])) {
$groupList[$k]['name'] = $v;
$groupList[$k]['achievement'] = $achievement->where('type', 2)->where($filter_w)->where('type_id', $k)->find();
$groupList[$k]['achievement'] = $groupList[$k]['achievement'] ?: $this->temp_achievement;
$list[] = $groupList[$k];
}
}
$total = count($list);
$result = array("total" => $total, "rows" => $list, "extend" => ['year' => $filter_w['year'], 'config' => isset($filter_w['config']) ? $filter_w['config'] : '']);
$this->success('',$result);
}
/**
* 员工业绩列表
* @ApiMethod (get)
*/
public function admin()
{
$achievement = new \app\admin\model\facrm\Achievement();
//设置过滤方法
$filter = $this->request->get("filter", '');
$filter = (array)json_decode($filter, true);
$filter_w = [];
if (isset($filter['search_time'])) {
$filter_w['year'] = $filter['search_time'];
unset($filter['search_time']);
} else {
$filter_w['year'] = date('Y', time());
}
if (isset($filter['config'])) {
$filter_w['config'] = $filter['config'];
unset($filter['config']);
} else {
$filter_w['config'] = 1;
}
$this->model =new \app\admin\model\Admin();
$childrenAdminIds = $this->getFilterChildrenAdminIds($filter);
if ($childrenAdminIds) {
$this->childrenAdminIds = $childrenAdminIds;
}
if (isset($filter['group_id'])) {
unset($filter['group_id']);
}
$this->request->get(['filter' => json_encode($filter)]);
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$list = $this->model
->where($where)
->where('id', 'in', $this->childrenAdminIds)
->field(['password', 'salt', 'token'], true)
->order($sort, $order)
->paginate($limit);
$this->temp_achievement['type'] = 3;
foreach ($list as $k => &$row) {
$row['achievement'] = $achievement->where('type', 3)->where($filter_w)->where('type_id', $row['id'])->find();
$row['achievement'] = $row['achievement'] ?: $this->temp_achievement;
}
unset($v);
$result = array("total" => $list->total(), "rows" => $list->items(), "extend" => ['year' => $filter_w['year'], 'config' => isset($filter_w['config']) ? $filter_w['config'] : '']);
$this->success('',$result);
}
/**
* 团队业绩编辑(单条)
* @ApiMethod (POST)
*/
public function edit()
{
$param = $this->request->param('row/a');
$field = $param['field'];
if (!isset($param['config']) || !in_array($param['config'], [1, 2])) {
$this->error(__("业绩方式有误"));
}
if (!isset($param['year']) && $param['year'] < 2000) {
$this->error(__("年份有误"));
}
if (!isset($param['group_id']) && $param['group_id'] < 0) {
$this->error(__("权限组有误"));
}
$where = [
'type' => 2,
'type_id' => $param['group_id'],
'year' => $param['year'],
'config' => $param['config'],
];
$achievement = new \app\admin\model\facrm\Achievement();
$row = $achievement->where($where)->find();
if (!is_numeric($param[$field]) || $param[$field] < 0) {
$this->error(__("请输入数字"));
}
if (!$row) {
//添加一条新记录
$this->temp_achievement['type_id'] = $param['group_id'];
$this->temp_achievement['year'] = $param['year'];
$this->temp_achievement['config'] = $param['config'];
$row = $achievement->create($this->temp_achievement);
if (!$row) {
$this->error(__("插入数据失败"));
}
$row = $achievement->find($row->id);
}
try {
$old_val = $row->$field;
if ($old_val == $param[$field]) {
$this->error(__("没有修改"));
} elseif ($old_val > $param[$field]) {
$row->yeartarget = $row->yeartarget - ($old_val - $param[$field]);
} elseif ($old_val < $param[$field]) {
$row->yeartarget = $row->yeartarget + ($param[$field] - $old_val);
}
$row->$field = $param[$field];
$row->config = $param['config'];
$row->save();
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success();
}
/**
* 成员业绩编辑(单条)
* @param null $ids
* @ApiMethod (POST)
*/
public function aedit()
{
$param = $this->request->param('row/a');
$field = $param['field'];
if (!isset($param['year']) && $param['year'] < 2000) {
$this->error(__("年份有误"));
}
if (!isset($param['admin_id']) && $param['admin_id'] < 0) {
$this->error(__("权限组有误"));
}
if (!isset($param['config']) || !in_array($param['config'], [1, 2])) {
$this->error(__("业绩方式有误"));
}
$where = [
'type' => 3,
'type_id' => $param['admin_id'],
'year' => $param['year'],
'config' => $param['config'],
];
$achievement = new \app\admin\model\facrm\Achievement();
$row = $achievement->where($where)->find();
if (!is_numeric($param[$field]) || $param[$field] < 0) {
$this->error(__("请输入数字"));
}
if (!$row) {
//添加一条新记录
$this->temp_achievement['type_id'] = $param['admin_id'];
$this->temp_achievement['year'] = $param['year'];
$this->temp_achievement['type'] = 3;
$this->temp_achievement['config'] = $param['config'];
$row = $achievement->create($this->temp_achievement);
if (!$row) {
$this->error(__("插入数据失败"));
}
$row = $achievement->find($row->id);
}
try {
$old_val = $row->$field;
if ($old_val == $param[$field]) {
$this->error(__("没有修改"));
} elseif ($old_val > $param[$field]) {
$row->yeartarget = $row->yeartarget - ($old_val - $param[$field]);
} elseif ($old_val < $param[$field]) {
$row->yeartarget = $row->yeartarget + ($param[$field] - $old_val);
}
$row->$field = $param[$field];
$row->save();
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->success();
}
/**
* 团队批量设置
*/
public function batchTeam(){
if ($this->request->isPost()) {
$param = $this->request->param('row/a');
if (!isset($param['config']) || !in_array($param['config'], [1, 2])) {
$this->error(__("业绩方式有误"));
}
if (!isset($param['year']) && $param['year'] < 2000) {
$this->error(__("年份有误"));
}
if (!isset($param['group_id']) && $param['group_id'] < 0) {
$this->error(__("部门有误"));
}
$where = [
'type' => 2,
'year' => $param['year'],
'config' => $param['config'],
];
$result=false;
if ($param['group_id']==0){
//全部
unset($param['group_id']);
foreach ($this->groupList as $g){
$achievement = new \app\admin\model\facrm\Achievement();
$where['type_id']=$g['id'];
$row = $achievement->where($where)->find();
$this->temp_achievement=array_merge($this->temp_achievement,$param);
$this->temp_achievement['type_id'] = $where['type_id'];
$this->temp_achievement['year'] = $where['year'];
if (!$row) {
//添加一条新记录
$result=$achievement->create($this->temp_achievement);
}else{
$result=$row->save($this->temp_achievement);
}
}
$this->success();
}else{
$achievement = new \app\admin\model\facrm\Achievement();
//某一个部门
$where['type_id']=$param['group_id'];
unset($param['group_id']);
$row = $achievement->where($where)->find();
$this->temp_achievement=array_merge($this->temp_achievement,$param);
$this->temp_achievement['type_id'] = $where['type_id'];
$this->temp_achievement['year'] = $where['year'];
if (!$row) {
//添加一条新记录
$result=$achievement->create($this->temp_achievement);
}else{
$result=$row->save($this->temp_achievement);
}
}
if ($result){
$this->success();
}else{
$this->error(__("添加失败"));
}
}
$this->error(__("提交方式错误"));
}
/**
* 成员批量设置
*/
public function batchAdmin(){
if ($this->request->isPost()) {
$param = $this->request->param('row/a');
if (!isset($param['config']) || !in_array($param['config'], [1, 2])) {
$this->error(__("业绩方式有误"));
}
if (!isset($param['year']) && $param['year'] < 2000) {
$this->error(__("年份有误"));
}
if (!isset($param['admin_id'])) {
$this->error(__("员工有误"));
}
$where = [
'type' => 3,
'year' => $param['year'],
'config' => $param['config'],
];
$result=false;
if ($param['admin_id']){
$this->childrenAdminIds=explode(",",$param['admin_id']);
}
//全部
unset($param['admin_id']);
$lists = \app\admin\model\Admin::where('id', 'in', $this->childrenAdminIds)
->field(['password', 'salt', 'token'], true)
->select();
foreach ($lists as $g){
$achievement = new \app\admin\model\facrm\Achievement();
$where['type_id']=$g['id'];
$row = $achievement->where($where)->find();
$this->temp_achievement=array_merge($this->temp_achievement,$param);
$this->temp_achievement['type_id'] = $where['type_id'];
$this->temp_achievement['year'] = $where['year'];
$this->temp_achievement['type']=$where['type'];
if (!$row) {
//添加一条新记录
$result=$achievement->create($this->temp_achievement);
}else{
$result=$row->isUpdate(true)->save($this->temp_achievement);
}
}
$this->success();
}
$this->error(__("提交方式错误"));
}
/**
* 过滤查找子用户
* @param $filter
* @return array|void
*/
protected function getFilterChildrenAdminIds($filter)
{
$childrenAdminIds = [];
if (isset($filter['group_id'])) {
$childrenAdminIds = [];
if ($filter['group_id'] > 0) {
Tree::instance()->init($this->groupList);
$groupIds = Tree::instance()->getChildrenIds($filter['group_id'], true);
$authGroupList = \app\admin\model\AuthGroupAccess::
field('uid,group_id')
->where('group_id', 'in', $groupIds)
->select();
foreach ($authGroupList as $k => $v) {
if (in_array($v['uid'], $childrenAdminIds)) continue;
$childrenAdminIds[] = $v['uid'];
}
if (!$childrenAdminIds) {
$this->error("该组下面没有成员");
}
}
}
return $childrenAdminIds;
}
}
... ...
<?php
namespace addons\facrm\controller\facrm;
use addons\facrm\library\BackendApi;
use think\Db;
use think\Exception;
/**
* 待办事项
*/
class Backlog extends BackendApi
{
protected $model = null;
/**
* 快速搜索时执行查找的字段
*/
protected $searchFields = 'customer_id,name,mobile,telephone';
protected $childrenAdminIds = [];
public function _initialize()
{
parent::_initialize();
$this->request->filter(['strip_tags']);
}
/**
* 待审批列表
* @ApiParams(name="types", type="string", required=true, description="contract合同审批,receivables回款审批,invoice发票审批")
*/
public function index()
{
$types = $this->request->request('types', "contract");
$filter_w = [];
if(!$model_str=\app\admin\model\facrm\Flow::getModelStr($types)){
$this->error(__("审核类型有误"));
}
$this->model = model($model_str);
//$filter_w[]=['exp','FIND_IN_SET('. $this->auth->id.',flow_admin_id)'];
// $filter_w[]=['exp','FIND_IN_SET(2,flow_admin_id)'];
$filter_w['check_status'] = ['in', [0, 1]];
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->where($where)
->where($filter_w)
->where('', 'exp', 'FIND_IN_SET(' . $this->auth->id . ',flow_admin_id)')
->order($sort, $order)->fetchSql(false)
->count();
$this->model
->where($where)
->where($filter_w)
->where('', 'exp', 'FIND_IN_SET(' . $this->auth->id . ',flow_admin_id)');
switch ($types) {
case 'receivables':
$this->model->with([
'createUser' => function ($user) {
$user->field('id,username,nickname');
},
'customer' => function ($customer) {
$customer->field('id,name');
},
'contract' => function ($customer) {
$customer->field('id,name,number');
},
]);
break;
case "contract":
$this->model->with([
'createUser' => function ($user) {
$user->field('id,username,nickname');
},
'orderAdmin' => function ($user) {
$user->field('id,username,nickname');
},
'customer' => function ($customer) {
$customer->field('id,name');
},
]);
break;
case "invoice":
$this->model->with([
'createUser' => function ($user) {
$user->field('id,username,nickname');
},
'contract' => function ($user) {
$user->field('id,number,name');
},
'customer' => function ($customer) {
$customer->field('id,name');
},
]);
break;
}
$list = $this->model->order($sort, $order)
->limit($offset, $limit)->fetchSql(false)
->select();
$result = array("rows" => $list);
$this->success('', $result);
}
/**
* 审批
* @ApiParams(name="types", type="string", required=true, description="contract合同审批,receivables回款审批")
* @ApiParams(name="id", type="int", required=true, description="对应的待审批id")
* @ApiParams(name="type", type="string", required=true, description="reject驳回,【审批的时候才需要】")
* @ApiParams(name="next_admin_id", type="string", required=true, description="下个审批人,多个逗号隔开,如果是选择审批的话,需要结束就不要传【审批的时候才需要】")
* @ApiParams(name="remark", type="string", required=true, description="备注,理由都是这个字段,【审批的时候才需要】")
* @ApiBody ("get是获取审批信息,post是审批")
*/
public function verify()
{
$types = $this->request->request('types', "contract");
$ids = $this->request->request('id', "0",'intval');
if(!$model_str=\app\admin\model\facrm\Flow::getModelStr($types)){
$this->error(__("审核类型有误"));
}
$this->model = model($model_str);
$Log = model('\app\admin\model\facrm\flow\Log');
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
if ($row->check_status == [0, 1]) {
$this->error(__('不是待审核'));
}
if (!in_array($this->auth->id, explode(',', $row->flow_admin_id))) {
$this->error(__('您没有权限审核'));
}
$flow = model('\app\admin\model\facrm\Flow');
$flow_r = $flow->where('types', $types)->where("status", 1)
->where('id', $row->flow_id)->find();
if (!$flow_r) {
$row->check_status=3;
$row->flow_id=0;
$row->flow_admin_id=$row->check_admin_id="";//已审批的人清空
$row->save();
$this->error(__('审核流程不存在,已经直接驳回!'));
}
$flow_r->step = $flow_r->step()->where('id', '>', $row->step_id)->select();
if ($this->request->isPost()) {
$type = $this->request->post("type");
$next_admin_id = $this->request->post("next_admin_id");
$log_data = array();
$log_data['flow_id'] = $row->flow_id;
$log_data['types'] = $types;
$log_data['types_id'] = $row->id;
$log_data['admin_id'] = $this->auth->id;
$log_data['nickname'] = $this->auth->nickname;
$log_data['remark'] = $this->request->post("remark", '');
$log_data['is_end'] = 0;
$log_data['status'] = 0;//未通过
Db::startTrans();
try {
//驳回
if ($type == 'reject') {
$row->check_status = 3;
$row->check_admin_id = "";//已审批的人清空
} else {
//通过
//判断是否还有下一级审批人
if ($flow_r->config == 1 && $flow_r->step) {
$flow_admin_id = $flow_r->step[0]['admin_ids'];
if ($flow_r->step[0]['type'] == 1) {
//上级领导审批
$parentIds = $this->auth->getParentAdminIds($this->auth->id);
$flow_admin_id = $parentIds ? join(',', $parentIds) : $this->auth->id;//如果没有父类就是最高级的,同时也要审核一下
}else if ($flow_r->step[0]['type']==3){
//指定部门
$auth=new \addons\facrm\library\Auth();
$groupIds=$auth->getGroupsAdminIds($flow_r->step[0]['admin_ids']);
$flow_admin_id=$groupIds?join(',',$groupIds):$this->auth->id;//如部门人自己也要审核一下
}
$row->check_status = 1;
$row->flow_admin_id = $flow_admin_id;
$row->step_id = $flow_r->step[0]['id'];
} elseif ($flow_r->config == 0 && $next_admin_id) {
$row->check_status = 1;
$row->flow_admin_id = $next_admin_id;
} else {
$row->flow_admin_id = "";
$row->check_status = 2;
$log_data['is_end'] = 1;
}
$row->check_admin_id .= $row->check_admin_id ? ',' . $this->auth->id : $this->auth->id;
$log_data['status'] = 1;//通过
}
$row->save();
//记录审核日志
$Log->save($log_data);
hook("facrm_flow_verify", array_merge($log_data, ['id' => $Log->id, 'flow' => $flow_r]));
Db::commit();
} catch (Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
$this->success();
}
$return_data=array();
//获取审核日志
$log_list = $Log->where('flow_id', $row->flow_id)->where('types_id', $row->id)->select();
$return_data['row']=$row;
$return_data['flow']=$flow_r;
$return_data['log_list']=$log_list;
switch ($types) {
case "contract":
$row->product;
break;
}
$this->success('',$return_data);
}
}
... ...
<?php
namespace addons\facrm\controller\facrm;
use addons\facrm\library\BackendApi;
use think\Config;
use think\Db;
use think\Exception;
use think\Hook;
use think\Request;
use app\common\exception\UploadException;
use app\common\library\Upload;
use think\Session;
/**
* 共有无需权限接口
* @internal
*/
class Common extends BackendApi
{
protected $noNeedRight = ['*'];
protected $noNeedLogin = ['init','getNoticeTpl'];
public function _initialize()
{
parent::_initialize();
//设置过滤方法
$this->request->filter(['trim', 'strip_tags', 'htmlspecialchars']);
}
/**
* 下拉选择
* @ApiParams(name="model", type="string", required=true, description="默认admin")
* @ApiParams(name="keyField", type="string", required=true, description="主键字段,如id")
* @ApiParams(name="type", type="string", required=false, description="可以空all代表获取全部")
*/
public function selectpage(){
$modellist=['admin'];
$model = $this->request->param('model');
if (!$this->request->request('keyField')){
$this->error("访问出错");
}
if (!in_array($model,$modellist))
$this->error("非法访问");
$this->model = model('\app\admin\model\\'.$model);
$type = $this->request->param('type');
switch ($model){
case 'admin':
$this->selectpageFields =['id','concat(nickname,"(",id,")") as nickname'];
$custom=['status'=>'normal'];
if ($type != "all") {
$childrenAdminIds = $this->auth->getChildrenAdminIds(true);
$custom['id']= ['in', $childrenAdminIds];
}
//暂时处理授权审批 检索员工出错问题
if (!$this->request->request('searchField')){
$this->request->request(['searchField' => 'nickname']);
}
$this->request->request(['custom' => $custom]);
break;
}
return parent::selectpage();
}
/**
* 读取省市区数据,联动列表
* @ApiMethod (GET)
* @ApiParams(name="province", type="int", required=true, description="省份ID,可空。空就是获取省份列表不空就是获取城市列表")
* @ApiParams(name="city", type="int", required=true, description="城市ID,可空,空就是获取城市列表不空就是获取区域列表")
*/
public function area()
{
$params = $this->request->get("row/a");
if (!empty($params)) {
$province = isset($params['province']) ? $params['province'] : '';
$city = isset($params['city']) ? $params['city'] : '';
} else {
$province = $this->request->get('province', '');
$city = $this->request->get('city', '');
}
$where = ['pid' => 0, 'level' => 1];
$provincelist = null;
if ($province !== '') {
$where['pid'] = $province;
$where['level'] = 2;
if ($city !== '') {
$where['pid'] = $city;
$where['level'] = 3;
}
}
$provincelist = Db::name('area')->where($where)->field('id as value,name')->select();
$this->success('', $provincelist);
}
/**
* 读取所有省市区数据(用于uview select)
*/
public function getAllArea(){
$lists= \addons\facrm\model\Area::getAllCacheChildren();
$this->success('',array_values($lists));
}
/**
* [客户等级、行业类型、来源等]
*/
public function baseConfig(){
$this->addon_config = get_addon_config('facrm');
$this->success('', [
'levelList'=>$this->addon_config['level'],
'industryList'=>$this->addon_config['industry'],
'sourceList'=>$this->addon_config['source'],
'accountList'=>$this->addon_config['account'],
'recordTypeList'=>$this->addon_config['record_type'],
'cprefix'=>$this->addon_config['cprefix'],//合同编号规则
'rprefix'=>$this->addon_config['rprefix'],//回款编号规则
'deal'=>$this->addon_config['deal'],//开启成交(无需走合同流程)
]
);
}
/**
* 基础配置
* @ApiParams (name="preview", type="int", required=false, description="只要传递说明是获取装修预览")
* @ApiReturnParams (name="login_captcha", type="string", required=false, sample="0",description="是否需要登录验证码")
* @ApiReturnParams (name="app_id", type="string", required=false, sample="",description="微信公众号ID")
* @ApiReturnParams (name="config.upload", type="array", required=false, sample="",description="上传配置,config.upload.cdnurl是图片地址cdn")
* @ApiReturnParams (name="themeconfig", type="obj", required=false, sample="",description="主题配色")
*/
public function init(){
$third=get_addon_config('third');
//配置信息
$upload = Config::get('upload');
//如果非服务端中转模式需要修改为中转
if ($upload['storage'] != 'local' && isset($upload['uploadmode']) && $upload['uploadmode'] != 'server') {
//临时修改上传模式为服务端中转
set_addon_config($upload['storage'], ["uploadmode" => "server"], false);
$upload = \app\common\model\Config::upload();
// 上传信息配置后
Hook::listen("upload_config_init", $upload);
$upload = Config::set('upload', array_merge(Config::get('upload'), $upload));
}
$upload['cdnurl'] = $upload['cdnurl'] ? $upload['cdnurl'] : \request()->domain();
$upload['uploadurl'] = preg_match("/^((?:[a-z]+:)?\/\/)(.*)/i", $upload['uploadurl']) ? $upload['uploadurl'] : url($upload['storage'] == 'local' ? '/api/common/upload' : $upload['uploadurl'], '', false, true);
$config = [
'upload' => $upload
];
$themeconfig=array();
if ($this->request->request('preview')){
$themeconfig=Session::get("facrmpreviewtheme");//用于预览
}
$themeconfig = $themeconfig?$themeconfig:\addons\facrm\library\Theme::get();
if ($themeconfig){
$themeconfig=\addons\facrm\library\Theme::render($themeconfig);
}
$payConfig=\addons\facrm\library\Order::getPayConfig();
$this->success('', [
'login_captcha'=>Config::get('fastadmin.login_captcha'),//是否需要验证码,
'app_id'=>isset($third['wechat']['app_id'])?$third['wechat']['app_id']:'',//企业微信公众号
'config'=>$config,//上传配置
'themeconfig'=>$themeconfig,//主题设置
'payConfig'=>($payConfig?$payConfig['values']:[]),//在线收款配置
]
);
}
/**
* 上传文件
* @ApiMethod (POST)
* @param File $file 文件流
*/
public function upload()
{
$upload_config=config("upload");
/**
* 兼容第三方存储,alioss,其它没有测试。
*/
if ($upload_config['storage']!='local'){
try {
Session::set("admin", $this->auth->getAdmin());//兼容需要登录的上传插件
request()->module('admin');
$objname="\\addons\\".$upload_config["storage"]."\\controller\\Index";
$uploadClass=new $objname();
$upload_config=config("upload");
if (isset($upload_config['multipart'])&&$upload_config['multipart']){
Request::instance()->post($upload_config['multipart']);
}
$uploadClass->upload();
}catch (Exception $e){
$this->error($e->getMessage());
}
}
Config::set('default_return_type', 'json');
//必须设定cdnurl为空,否则cdnurl函数计算错误
Config::set('upload.cdnurl', '');
$chunkid = $this->request->post("chunkid");
if ($chunkid) {
if (!Config::get('upload.chunking')) {
$this->error(__('Chunk file disabled'));
}
$action = $this->request->post("action");
$chunkindex = $this->request->post("chunkindex/d");
$chunkcount = $this->request->post("chunkcount/d");
$filename = $this->request->post("filename");
$method = $this->request->method(true);
if ($action == 'merge') {
$attachment = null;
//合并分片文件
try {
$upload = new Upload();
$attachment = $upload->merge($chunkid, $chunkcount, $filename);
} catch (UploadException $e) {
$this->error($e->getMessage());
}
$this->success(__('上传成功'), ['url' => $attachment->url, 'fullurl' => cdnurl($attachment->url, true)]);
} elseif ($method == 'clean') {
//删除冗余的分片文件
try {
$upload = new Upload();
$upload->clean($chunkid);
} catch (UploadException $e) {
$this->error($e->getMessage());
}
$this->success();
} else {
//上传分片文件
//默认普通上传文件
$file = $this->request->file('file');
try {
$upload = new Upload($file);
$upload->chunk($chunkid, $chunkindex, $chunkcount);
} catch (UploadException $e) {
$this->error($e->getMessage());
}
$this->success();
}
} else {
$attachment = null;
//默认普通上传文件
$file = $this->request->file('file');
try {
$upload = new Upload($file);
$attachment = $upload->upload();
} catch (UploadException $e) {
$this->error($e->getMessage());
}
$this->success(__('上传成功'), ['url' => $attachment->url, 'fullurl' => cdnurl($attachment->url, true)]);
}
}
/**
* 获取通知模板
* @ApiParams (name="type", type="string", required=false, sample="0",description="flow_contract,flow_invoice,clues_customer,flow_receivables,flow_business")
*/
public function getNoticeTpl(){
$engine = $this->request->request('engine','Min');
$type = $this->request->request('type','');//flow_contract ,flow_receivables,clues_customer,flow_business
//由于微信订阅通知最多只能有3条订阅 所以专门做了此修改
//审批合同相关通知,
$flow_contract=['notice_flow_contract','notice_pass_contract','notice_nopass_contract'];
//审批回款通知
$flow_receivables=['notice_pass_receivables','notice_flow_receivables','notice_nopass_receivables'];
//线索和客户
$clues_customer=['notice_flow_customer','notice_expire_ccustomer','notice_flow_clues'];
//商机
$flow_business=['notice_flow_business'];
//发票
$flow_invoice=['notice_flow_invoice_nopass','notice_invoice_opener'];
$data_temp = \addons\facrm\library\notice\Notice::getTempLplData();
$keys=array();
foreach ( $data_temp as $row){
if(isset($$type)&&in_array($row['key'],$$type)){
$keys[]=$row['key'].$engine;
}
}
$lists=\app\admin\model\facrm\Setting::where('key','in',$keys)->where('status',1)->select();
$this->success('',$lists);
}
/**
* 检查权限
*/
public function authcheck(){
$auth = $this->request->post('auth');
$this->success('',($auth&&$this->auth->check($auth))?1:0);
}
/**
* 腾讯地图经纬度返回地址
* @ApiParams (name="lat", type="string", required=true, description="lat<纬度>,lng<经度>")
* @ApiParams (name="lng", type="string", required=true, description="lat<纬度>,lng<经度>")
* @ApiReturnParams (name="address", type="string", required=true, sample="0",description="定位地址")
*/
public function geocoder(){
$url="https://apis.map.qq.com/ws/geocoder/v1/";
$addon_config = get_addon_config('facrm');
if (!isset($addon_config['map_qq_key'])||!$addon_config['map_qq_key']){
$this->error('腾讯地图KEY未配置');
}
//lat<纬度>,lng<经度>
$lat=$this->request->get('lat');
$lng=$this->request->get('lng');
//location= 39.984154,116.307490
if (!$lat||!$lng){
$this->error("经纬度有误");
}
$params=['location'=>"{$lat},{$lng}",'key'=>$addon_config['map_qq_key']];
$cachekey=md5("{$lat},{$lng}");
$result=cache($cachekey);
if (!$result){
//缓存没有才去接口那里获取
$result=\fast\Http::get($url,$params);
$result=json_decode($result,true);
if (!$result||!isset($result['status'])||$result['status']!=0||!isset($result['result']['address'])){
$this->error('获取地址错误');
}
cache($cachekey,$result,86400*30);
}
$this->success('',['address'=>$result['result']['address']]);
}
}
... ...
<?php
namespace addons\facrm\controller\facrm;
use addons\facrm\library\BackendApi;
use app\admin\model\AuthGroup;
use app\admin\model\facrm\Contract;
use app\admin\model\facrm\contract\Receivables;
use addons\facrm\model\Admin as AdminModel;
use fast\Tree;
/**
* 首页
* @icon fa fa-dashboard
* @remark 用于展示当前系统中的统计数据、统计报表及重要实时数据
*/
class Dashboard extends BackendApi
{
protected $groupList = [];
protected $groupdata = [];
protected $noNeedRight = ['getAchievement','getNotice'];
public function _initialize()
{
parent::_initialize();
$this->model = new AdminModel();
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
$this->childrenGroupIds = $this->auth->getChildrenGroupIds(true);
$this->groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray();
Tree::instance()->init($this->groupList);
if ($this->auth->isSuperAdmin()) {
$result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
foreach ($result as $k => $v) {
$this->groupdata[$v['id']] = $v['name'];
}
} else {
$result = [];
$groups = $this->auth->getGroups();
foreach ($groups as $m => $n) {
$childlist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['id']));
$temp = [];
foreach ($childlist as $k => $v) {
$temp[$v['id']] = $v['name'];
}
$result[__($n['name'])] = $temp;
}
$this->groupdata = $result;
}
}
/**
* 首页数据
* @ApiMethod (POST|GET)
* @ApiParams(name="type", type="string", required=true, description="oneself:自己,team团队")
* @ApiReturnParams (name="communicate", type="int", required=false, sample="0",description="待跟进客户")
* @ApiReturnParams (name="lose_num", type="int", required=false, sample="0",description="将过期客户")
* @ApiReturnParams (name="business", type="int", required=false, sample="0",description="待跟进商机")
* @ApiReturnParams (name="contract_expire", type="int", required=false, sample="0",description="过期合同")
* @ApiReturnParams (name="contract_return", type="int", required=false, sample="0",description="待回款合同")
* @ApiReturnParams (name="contract_flow", type="int", required=false, sample="0",description="待审核合同")
* @ApiReturnParams (name="receivables_flow", type="int", required=false, sample="0",description="待审核回款")
* @ApiReturnParams (name="clues_num", type="int", required=false, sample="0",description="待跟进线索")
*/
public function index()
{
$year = $this->request->param('year', date("Y", time()), 'intval');
$month = $this->request->param('month', intval(date("m", time())), 'intval');
$config = $this->request->param('config', 1, 'intval');//$config 1=>'合同金额',2=>'回款金额'
$group_id = $this->request->param('group_id', 0, 'intval');//部门
$admin_id = $this->request->param('admin_id', 0, 'intval');//员工
$type = $this->request->param('type', 'oneself');
$achievementModel = new \app\admin\model\facrm\Achievement();
//当天开始时间
$start_time = strtotime(date("Y-m-d", time()));
//当天结束之间
$end_time = $start_time + 60 * 60 * 24;
switch ($type) {
case 'oneself':
$return_data=$this->getNotice(true);
if (!$achievement = $achievementModel->achievement($config, $year, $month, 3, $this->auth->id, $this->auth->id)) {
$this->error($achievementModel->getError());
}
$return_data['achievement'] = $achievement;
//自己的end
break;
case 'team':
$return_data=$this->getNotice(true);
if ($group_id && !$admin_id) {
//如果有选团队并且没有选员工就是团队业绩
Tree::instance()->init($this->groupList);
$this->childrenGroupIds = Tree::instance()->getChildrenIds($group_id, true);
$authGroupList = \app\admin\model\AuthGroupAccess::
field('uid,group_id')
->where('group_id', 'in', $this->childrenGroupIds)
->select();
$this->childrenAdminIds=[];
foreach ($authGroupList as $k => $v) {
if ($this->childrenAdminIds && in_array($v['uid'], $this->childrenAdminIds)) continue;
$this->childrenAdminIds[] = $v['uid'];
}
} else if($admin_id) {
$this->childrenAdminIds = $admin_id ;
$this->childrenGroupIds=$admin_id;
}
$team_achievement = $achievementModel->achievement($config, $year, $month, 2, $this->childrenGroupIds, $this->childrenAdminIds);
$team_achievement['config']=$config;
$return_data =array_merge($return_data,
[
'achievement' => $team_achievement,
]) ;
break;
//团队的end
default:
$this->error(__("访问有误"));
}
$this->success('', $return_data);
}
/**
* 消息和提醒
* @ApiParams(name="type", type="string", required=true, description="oneself:自己,team团队")
* @ApiReturnParams (name="communicate", type="int", required=false, sample="0",description="待跟进客户")
* @ApiReturnParams (name="lose_num", type="int", required=false, sample="0",description="将过期客户")
* @ApiReturnParams (name="business", type="int", required=false, sample="0",description="待跟进商机")
* @ApiReturnParams (name="contract_expire", type="int", required=false, sample="0",description="过期合同")
* @ApiReturnParams (name="contract_return", type="int", required=false, sample="0",description="待回款合同")
* @ApiReturnParams (name="contract_flow", type="int", required=false, sample="0",description="待审核合同")
* @ApiReturnParams (name="receivables_flow", type="int", required=false, sample="0",description="待审核回款")
* @ApiReturnParams (name="clues_num", type="int", required=false, sample="0",description="待跟进线索")
* @ApiReturnParams (name="invoice_flow", type="int", required=false, sample="0",description="待审批发票")
* @ApiReturnParams (name="invoice_opener", type="int", required=false, sample="0",description="待开具发票")
*/
public function getNotice($isReturn=false){
$type = $this->request->param('type', 'oneself');
$businessModel = model('\app\admin\model\facrm\Business');
$customerModel = model('\app\admin\model\facrm\Customer');
$cluesModel = model('\app\admin\model\facrm\Clues');
$contractModel = model('\app\admin\model\facrm\Contract');
$receivablesModel = model('\app\admin\model\facrm\contract\Receivables');
$invoiceModel = model('\app\admin\model\facrm\Invoice');
//当天开始时间
$start_time = strtotime(date("Y-m-d", time()));
//当天结束之间
$end_time = $start_time + 60 * 60 * 24;
//更新到期回款计划
$planModel =new \app\admin\model\facrm\contract\Plan();
$planModel->where('plan_time', '<', time())->where('status',0)->update(['status'=>'-1']);
$plan=0;
if ($this->auth->check('facrm/contract/plan/index')){
$time=time();
$planModel->with(['contract']);
if (!$this->auth->isSuperAdmin() && !$this->auth->check('facrm/contract/index/index')) {
$planModel->where('contract.order_admin_id', 'in', $this->auth->getChildrenAdminIds(true));
}
$plan=$planModel->where('plan_time','<',\think\Db::raw(" ({$time}+(`remind_day`*86400))"))->where('status','neq',2)
->fetchSql(false)->count();
}
switch ($type) {
case 'oneself':
//自己的start
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
$filter_w['owner_user_id'] = $this->auth->id;
//需要联系客户
$communicate = $customerModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count();
//待跟进线索
$clues_num = $cluesModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count();
//将要过期的客户
$lose_num = count($customerModel->getLose($this->auth->id));
$business = $businessModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count();
//是否有合同权限
$contract_return = $contract_expire = 0;
if ($this->auth->check('facrm/contract/index')) {
$filter_w['check_status'] = 2;
//快过期和过期合同
$contract_expire = $contractModel->where('end_time', 'between', [1, $end_time + (30 * 86400)])->where('expire_handle', 0)->where($filter_w)->count();
//待回款合同
$contract_return = $contractModel->where("money", "exp", ">return_money")->where($filter_w)->count();
}
//合同审核和回款审核
$contract_flow = $contractModel->where('find_in_set(:id,flow_admin_id)', ['id' => $this->auth->id])->where('check_status', 'in', [0, 1])->count();
$receivables_flow = $receivablesModel->where('find_in_set(:id,flow_admin_id)', ['id' => $this->auth->id])->where('check_status', 'in', [0, 1])->count();
//待审发票
$invoice_flow=$invoiceModel->where('find_in_set(:id,flow_admin_id)', ['id' => $this->auth->id])->where('check_status', 'in', [0, 1])->count();
//待开具发票
$invoice_opener=$invoiceModel->where('status', 'in', [0, 1])->where('check_status', 2)->count();
$return_data = [
'communicate' => $communicate,//待跟进客户
'lose_num' => $lose_num, //将过期客户
'business' => $business,//待跟进商机
'contract_expire' => $contract_expire,//过期合同
'contract_return' => $contract_return,//待回款合同
'contract_flow' => $contract_flow,//待合同审核
'receivables_flow' => $receivables_flow,//待回款审核
'clues_num'=>$clues_num,//待跟进线索
'invoice_flow'=> $invoice_flow,
'invoice_opener'=>$invoice_opener,
'plan'=>$plan
];
//自己的end
break;
case 'team':
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
//团队的
$filter_w = array();
$filter_w['owner_user_id'] = ['in', $this->childrenAdminIds];
//需要联系客户
$team_communicate = $customerModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count();
//待跟进线索
$clues_num = $cluesModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count();
//将要过期的用户
$team_lose_num = count($customerModel->getLose($this->childrenAdminIds));
$team_business = $businessModel->where('next_time', 'between', [1, $end_time])->where($filter_w)->count();
//是否有合同权限
$team_contract_return = $team_contract_expire = 0;
if ($this->auth->check('facrm/contract/index')) {
$filter_w['check_status'] = 2;
//快过期和过期合同
$team_contract_expire = $contractModel->where('end_time', 'between', [1, $end_time + (30 * 86400)])->where('expire_handle', 0)->where($filter_w)->count();
//待回款合同
$team_contract_return = $contractModel->where("money", "exp", ">return_money")->where($filter_w)->count();
}
$return_data = [
'communicate' => $team_communicate,
'lose_num' => $team_lose_num,
'clues_num'=>$clues_num,//待跟进线索
'business' => $team_business,
'contract_expire' => $team_contract_expire,
'contract_return' => $team_contract_return,
'plan'=>$plan
];
break;
//团队的end
default:
$this->error(__("访问有误"));
}
if ($isReturn){
return $return_data;
}
$this->success('', $return_data);
}
}
... ...
<?php
namespace addons\facrm\controller\facrm;
use addons\facrm\library\BackendApi;
use app\common\model\Config;
use fast\Tree;
use think\Db;
/**
* 自定义字段
*
* @icon fa fa-circle-o
*/
class Fields extends BackendApi
{
/**
* Fields模型对象
*/
protected $model = null;
protected $modelValidate = true;
protected $modelSceneValidate = true;
protected $noNeedRight = ['get_fields','selectpage'];
private $modelList = array();
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\facrm\Fields;
$this->modelList = [
'customer' => __('客户'),
'customer_contacts' => __('联系人'),
'contract'=>__("合同"),
'contract_receivables'=>__("回款"),
'business'=>__("商机"),
'clues'=>__("线索"),
];
$this->request->filter(['strip_tags']);
}
/**
* 获取自定义字段
* @ApiParams(name="source", type="string", required=true, description="customer:客户,customer_contacts联系人")
* @ApiParams(name="id", type="int", required=true, description="对应数据的id")
*/
public function get_fields()
{
$source=$this->request->request('source','');
if (!in_array($source, array_keys($this->modelList))) {
$this->error(__("未开放信息"));
}
$source=ucfirst($source);
$id = $this->request->param('id', 0, 'intval');
switch ($source) {
case 'Contract_receivables':
$this->model = model('\app\admin\model\facrm\contract\Receivables');
break;
case 'Customer_contacts':
$this->model = model('\app\admin\model\facrm\customer\Contacts');
break;
default:
$this->model = model("\\app\\admin\\model\\facrm\\{$source}");
}
$values = [];
if ($id > 0) {
$values = $this->model->find($id);
}
$fields = \app\admin\model\facrm\Fields::getCustomFields($source, $values);
if ($values&&$fields){
foreach ($fields as &$row){
if (isset($values[$row['name']]))$row['value']=$values[$row['name']];
}
}
$this->success('',array('fields'=> $fields));
}
/**
* 关联表联动
* @internal
*/
public function selectpage()
{
$id = $this->request->get("id/d", 0);
$fieldInfo = $this->model::get($id);
if (!$fieldInfo) {
$this->error("未找到指定字段");
}
$setting = $fieldInfo['setting'];
if (!$setting || !isset($setting['table'])) {
$this->error("字段配置不正确");
}
//搜索关键词,客户端输入以空格分开,这里接收为数组
$word = (array)$this->request->request("q_word/a");
//当前页
$page = $this->request->request("pageNumber");
//分页大小
$pagesize = $this->request->request("pageSize");
//搜索条件
$andor = $this->request->request("andOr", "and", "strtoupper");
//排序方式
$orderby = (array)$this->request->request("orderBy/a");
//显示的字段
//$field = $this->request->request("showField");
$field = $setting['field'];
//主键
//$primarykey = $this->request->request("keyField");
$primarykey = $setting['primarykey'];
//主键值
$primaryvalue = $this->request->request("keyValue");
//搜索字段
$searchfield = (array)$this->request->request("searchField/a");
$searchfield = [$field, $primarykey];
//自定义搜索条件
$custom = (array)$this->request->request("custom/a");
$custom = isset($setting['conditions']) ? (array)json_decode($setting['conditions'], true) : [];
$custom = array_filter($custom);
$admin_id = session('admin.id') ?: 0;
$user_id = $this->auth->id ?: 0;
//如果是管理员需要移除user_id筛选,否则会导致管理员无法筛选列表信息
$admin = $this->request->request("admin/d");
if ($admin_id && $admin) {
unset($custom['user_id']);
} else {
//如果不是管理员则需要判断是否开放相应的投稿字段
if (!in_array($fieldInfo['source'], array_keys($this->modelList))) {
$this->error("未开放栏目信息");
}
}
//是否返回树形结构
$istree = $this->request->request("isTree", 0);
$ishtml = $this->request->request("isHtml", 0);
if ($istree) {
$word = [];
$pagesize = 99999;
}
$order = [];
foreach ($orderby as $k => $v) {
$order[$v[0]] = $v[1];
}
$field = $field ? $field : 'name';
//如果有primaryvalue,说明当前是初始化传值
if ($primaryvalue !== null) {
$where = [$primarykey => ['in', $primaryvalue]];
$where = function ($query) use ($primaryvalue, $custom, $admin_id, $user_id) {
$query->where('id', 'in', $primaryvalue);
if ($custom && is_array($custom)) {
//替换暂位符
$search = ["{admin_id}", "{user_id}"];
$replace = [$admin_id, $user_id];
foreach ($custom as $k => $v) {
if (is_array($v) && 2 == count($v)) {
$query->where($k, trim($v[0]), str_replace($search, $replace, $v[1]));
} else {
$query->where($k, '=', str_replace($search, $replace, $v));
}
}
}
};
$pagesize = 99999;
} else {
$where = function ($query) use ($word, $andor, $field, $searchfield, $custom, $admin_id, $user_id) {
$logic = $andor == 'AND' ? '&' : '|';
$searchfield = is_array($searchfield) ? implode($logic, $searchfield) : $searchfield;
$word = array_filter($word);
if ($word) {
foreach ($word as $k => $v) {
$query->where(str_replace(',', $logic, $searchfield), "like", "%{$v}%");
}
}
if ($custom && is_array($custom)) {
//替换暂位符
$search = ["{admin_id}", "{user_id}"];
$replace = [$admin_id, $user_id];
foreach ($custom as $k => $v) {
if (is_array($v) && 2 == count($v)) {
$query->where($k, trim($v[0]), str_replace($search, $replace, $v[1]));
} else {
$query->where($k, '=', str_replace($search, $replace, $v));
}
}
}
};
}
$list = [];
$total = Db::table($setting['table'])->where($where)->count();
if ($total > 0) {
$datalist = Db::table($setting['table'])->where($where)
->order($order)
->page($page, $pagesize)
->field($primarykey . "," . $field . ($istree ? ",pid" : ""))
->select();
foreach ($datalist as $index => &$item) {
unset($item['password'], $item['salt']);
$list[] = [
$primarykey => isset($item[$primarykey]) ? $item[$primarykey] : '',
$field => isset($item[$field]) ? $item[$field] : '',
'pid' => isset($item['pid']) ? $item['pid'] : 0
];
}
if ($istree && !$primaryvalue) {
$tree = Tree::instance();
$tree->init($list, 'pid');
$list = $tree->getTreeList($tree->getTreeArray(0), $field);
if (!$ishtml) {
foreach ($list as &$item) {
$item = str_replace('&nbsp;', ' ', $item);
}
unset($item);
}
}
}
//这里一定要返回有list这个字段,total是可选的,如果total<=list的数量,则会隐藏分页按钮
$this->success('', ['list' => $list, 'total' => $total]);
}
}
... ...
<?php
namespace addons\facrm\controller\facrm;
use addons\facrm\library\BackendApi;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use think\exception\ValidateException;
/**
* 发票管理
*/
class Invoice extends BackendApi
{
protected $model = null;
/**
* 快速搜索时执行查找的字段
*/
protected $searchFields = 'invoice_name';
protected $childrenAdminIds = [];
protected $noNeedRight = [ 'selectpage','history'];
protected $tpl_key="invoice_tpl";
public function _initialize()
{
parent::_initialize();
$this->model = model('\app\admin\model\facrm\Invoice');
//设置过滤方法
$this->request->filter(['trim', 'strip_tags', 'htmlspecialchars']);
}
/**
* 我申请的发票
* @ApiSummary (返回值里面有scene_list,如果有all全部发票就有权限)
* @ApiMethod (GET)
* @ApiReturnParams (name="scene_list", type="array", required=true, sample="0")
* @ApiBody ("filter里面的scene_id是必传的,参考PC[owner我申请的发票,branch下属申请的发票all全部申请的发票]")
*/
public function index($scene_list=array())
{
//设置过滤方法
$this->request->filter(['strip_tags']);
$scene_list = $scene_list?$scene_list:['owner'=>'我申','branch'=>'下属'];
$customer_id = $this->request->param("customer_id");
$filter_w = $this->getFilterWhere($scene_list);
if ($customer_id) {
$filter_w['customer_id'] = $customer_id;
}
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
$this->request->request(['custom' => $filter_w]);
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->where($where)
->where($filter_w)
->with([
])
->order($sort, $order)->fetchSql(false)
->count();
$list = $this->model
->where($where)
->where($filter_w)
->with([
'createUser' => function ($user) {
$user->field('id,username,nickname');
},
'contract' => function ($user) {
$user->field('id,name,number');
},
'customer' => function ($customer) {
$customer->field('id,name');
},
])
->order($sort, $order)
->limit($offset, $limit)->fetchSql(false)
->select();
$scene_list=['owner'=>'我申发票'];
if ($this->auth->check('facrm/invoice/index/lists')){
$scene_list['all']="全部发票";
}
if ($this->auth->check('facrm/invoice/index/opener')){
$scene_list['opener']="财务待开";
}
$this->success('',array( "total" => $total,"rows" => $list,'scene_list'=>$scene_list));
}
/**
* 全部发票
* @ApiMethod (GET)
* @ApiBody ("filter里面的scene_id是必须是all")
*/
public function lists(){
return $this->index(['all'=>'全部发票']);
}
/**
* 申请
* @ApiMethod (GET)
* @return mixed
* @ApiBody ("GET获取参数,【flow审核配置,setting发票配置】,POST提交申请,参数参考PC")
*/
public function add()
{
$flow = model('\app\admin\model\facrm\Flow');
$flow_r =\app\admin\model\facrm\Flow::getFlow($this->auth->id, 'invoice');
if (!$flow_r) $this->error(__('审批配置不存在,请先配置'));
//获取发票配置
$settingModel = new \app\admin\model\facrm\Setting();
$setting = $settingModel->where('key',$this->tpl_key)->where('status',1)->value('values');
if (!$setting){
$this->error(__('发票开具申请未开启'));
}
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if (!isset($params['contract_id']))
$this->error(__('请选择合同'));
$contractModel = new \app\admin\model\facrm\Contract();
//获取合同情况
$contract_r = $contractModel->get($params['contract_id']);
if (!$contract_r)
$this->error(__('没有找到合同'));
if ($contract_r['check_status']!=2)
$this->error(__('合同未通过审核不能申请发票'));
if ($this->model->where('contract_id',$contract_r['id'])->where(function ($query){
$query->where('check_status','in',[0,1])->whereOr('status','in',[0,1]);
})->count()){
$this->error(__("该合同还有未审批或未开票的申请"));
}
//判断开票金额,不能大于合同金额且不能大于回款金额
$money=bcadd($params['money'],$contract_r['invoice_money'],2);
if ($money>$contract_r['money']&&$money>$contract_r['return_money']){
$this->error(__("累计开票金额,不能大于合同金额且不能大于回款金额"));
}
$params = array_merge($params, [
'create_admin_id' => $this->auth->id,
'invoice_admin_id' => 0,
'customer_id'=>$contract_r['customer_id'],
'status' =>0,
'check_status' => 0,
]);
$result = false;
$invoice_id = 0;
Db::startTrans();
try {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
$this->model->validateFailException(true)->validate( $name . '.add');
$result = $this->model->allowField(true)->save($params);
$invoice_id = $this->model->id;
Db::commit();
} catch (ValidateException $e) {
Db::rollback();
$this->error($e->getMessage());
} catch (PDOException $e) {
Db::rollback();
$this->error($e->getMessage());
} catch (Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if ($result !== false) {
//处理合同审核流程
$flow->addFlow($invoice_id, $this->auth->id, 'invoice', $flow_r);
hook("facrm_invoice_add", array_merge($params, ['id' => $invoice_id]));
$this->success();
} else {
$this->error(__('No rows were inserted'));
}
}
$setting=json_decode($setting,true);
if ($flow_r->config==1)//如果固定审批
$flow_r['flow_admin_id']=$flow->getAdminIds($flow_r,$this->auth->id);
$this->success('',array('flow'=>$flow_r,'setting'=>$setting));
}
/**
* 获取客户历史发票资料
* @ApiSummary (用于自动完成发票信息填写)
* @ApiParams (name="contract_id", type="integer", required=true, description="合同ID")
* @return mixed
*/
public function history($contract_id=NULL){
$contract_id = $this->request->request('contract_id', '', 'intval');
if (!$this->auth->check('facrm/invoice/add')){
$this->error(__('You have no permission'));
}
if (!$contract_id) {
$this->error(__('No Results were found'));
}
//获取合同信息
$contractModel= new \app\admin\model\facrm\Contract();
$contract=$contractModel->where('id',$contract_id)->find();
if (!$contract){
$this->error(__('合同信息不存在'));
}
$invoice =$this->model->where('customer_id',$contract->customer_id)->orderRaw("field(check_status,'2','1','0','3')")->order('id desc')->fetchSql(false)->find();
if ($invoice) {
$invoice->hidden(['files']);
}
$this->success('',[
'contract'=>[
'money'=>$contract['money'],
'return_money'=>$contract['money'],
'invoice_money'=>$contract['invoice_money']
],
'invoice'=>$invoice
]);
}
/**
* 修改
* @ApiSummary (用于自动完成发票信息填写)
* @ApiParams (name="ids", type="integer", required=true, description="ID")
* @ApiBody ("GET获取参数,【flow审核配置,row发票数据】,POST提交申请,参数参考PC")
*/
public function edit($ids = NULL)
{
$ids = $this->request->request('ids', '', 'intval');
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
$flow = model('\app\admin\model\facrm\Flow');
if ($row->flow_id){
$flow->where('id',$row->flow_id);//处理流程被删除
}
$flow_r = $flow->where('types', 'invoice')->where("status", 1)->find();
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
if ($row->check_status == 2) {
//审核通过的只能修改负责人和备注、处理情况、续费单价
$params_update =array();
isset($params['remarks'])?$params_update['remarks']=$params['remarks']:'';
$result = $row->allowField(true)->save($params_update);
$this->success();
}
/* elseif ($row->check_status == 1) {
//审核中的不能修改
$this->error(__("审核中的不能修改,请先驳回再修改"));
}*/
$params['check_status'] = 0;//重新改成待审核状态
//获取合同情况
$contract_r = $row->contract;
if (!$contract_r)
$this->error(__('没有找到合同'));
if ($contract_r['check_status']!=2)
$this->error(__('合同未通过审核不能申请发票'));
//判断开票金额,不能大于合同金额且不能大于回款金额
$money=bcadd($params['money'],$contract_r['invoice_money'],2);
if ($money>$contract_r['money']&&$money>$contract_r['return_money']){
$this->error(__("累计开票金额,不能大于合同金额且不能大于回款金额"));
}
$result = false;
Db::startTrans();
try {
//是否采用模型验证
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
$row->validateFailException(true)->validate($name . '.edit');
$invoice_id = $row->id;
$result = $row->allowField(true)->save($params);
if ($result) {
}
Db::commit();
} catch (ValidateException $e) {
Db::rollback();
$this->error($e->getMessage());
} catch (PDOException $e) {
Db::rollback();
$this->error($e->getMessage());
} catch (Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if ($result !== false) {
//处理合同审核流程
$flow->addFlow($invoice_id, $this->auth->id, 'invoice', $flow_r);
hook("facrm_invoice_edit", array_merge($params, ['id' => $invoice_id]));
$this->success();
} else {
$this->error(__('No rows were updated'));
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
$row=$row->toArray();
//处理附件
if ($row['files']){
$row['files']=explode(',',$row['files']);
foreach ($row['files'] as &$val){
$val=cdnurl($val,true);
}
}
$this->success('',array('flow'=>$flow_r,'row'=>$row));
}
/**
* 开具
* @ApiSummary (用于自动完成发票信息填写)
* @ApiParams (name="ids", type="integer", required=true, description="ID")
* @ApiBody ("GET获取参数,【row发票数据】,POST提交申请,参数参考PC")
*/
public function opener($ids=NULL){
$ids = $this->request->request('ids', '', 'intval');
//其实就是把发票附件上传
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
if ($row->status==2){
$this->error(__('已开具,不能重复开具'));
}
if ($this->request->isPost()){
$params = $this->request->post("row/a");
if ($params) {
$params['status']=2;
$result = $row->allowField(true)->save($params);
if ($result){
$row->contract()->setInc('invoice_money', $row->money);
//钩子
hook("facrm_invoice_opener", array_merge($row->toArray(),$params));
$this->success("成功");
}
}
$this->error(__('No rows were updated'));
}
$this->success('',array('row'=>$row));
}
/**
* 删除
* @param string $ids
*/
public function del($ids = "")
{
if (!$this->request->isPost()) {
$this->error(__("Invalid parameters"));
}
$ids = $ids ? $ids : $this->request->post("ids");
if ($ids) {
$pk = $this->model->getPk();
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
$list = $this->model->where($pk, 'in', $ids)->where('create_admin_id', 'in', $this->childrenAdminIds)->select();
$count = 0;
Db::startTrans();
try {
foreach ($list as $k => $v) {
$count += $v->delete();
}
Db::commit();
} catch (PDOException $e) {
Db::rollback();
$this->error($e->getMessage());
} catch (Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if ($count) {
$this->success();
} else {
$this->error(__('No rows were deleted'));
}
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
/**
* 处理过滤where条件
* @return array
*/
private function getFilterWhere($scene_list)
{
$filter = $this->request->get("filter", '');
$filter = (array)json_decode($filter, true);
$filter_w = [];
$filter['scene_id'] = isset($filter['scene_id']) ? $filter['scene_id'] : 1;
if (isset($filter['scene_id'])) {
if (!isset($scene_list[$filter['scene_id']])) {
$this->error(__("您没有权限"));
}
switch ($filter['scene_id']) {
case 'all':
//全部
break;
case 'owner':
//我的
$filter_w['create_admin_id'] = $this->auth->id;
break;
case 'branch':
//下级
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(false);
$filter_w['create_admin_id'] = ['in', $this->childrenAdminIds];
break;
default://其它的未做 TODO
$filter_w['create_admin_id'] = $this->auth->id;
}
unset($filter['scene_id']);
$this->request->get(['filter' => json_encode($filter)]);
}
return $filter_w;
}
}
... ...
<?php
namespace addons\facrm\controller\facrm;
use addons\facrm\library\BackendApi;
/**
* 操作记录
*/
class Operatelog extends BackendApi
{
protected $model = null;
protected $noNeedRight = ['index'];
/**
* 快速搜索时执行查找的字段
*/
protected $searchFields = 'content';
public function _initialize()
{
parent::_initialize();
$this->model = model('\app\admin\model\facrm\Operatelog');
$this->request->filter(['strip_tags']);
}
/**
* 查看
* @ApiSummary (参数根据实际需要传,不需要三个都一起传)
* @ApiMethod (GET)
* @ApiParams (name="customer_id", type="int", required=false, description="客户ID")
* @ApiParams (name="contract_id", type="int", required=false, description="合同ID")
* @ApiParams (name="receivable_id", type="int", required=false, description="回款ID")
* @ApiBody ("有分页")
*/
public function index($customer_id = null, $contract_id = null, $receivable_id = null)
{
$customer_id = $customer_id ? $customer_id : $this->request->param("customer_id");
$contract_id = $contract_id ? $contract_id : $this->request->param("contract_id");
$receivable_id = $receivable_id ? $receivable_id : $this->request->param("receivable_id");
$filter_w = [];
if ($customer_id) {
$filter_w['customer_id'] = $customer_id;
}
if ($contract_id) {
$filter_w['contract_id'] = $contract_id;
}
if ($receivable_id) {
$filter_w['receivable_id'] = $receivable_id;
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->where($where)
->where($filter_w)
->order($sort, $order)->fetchSql(false)
->count();
$list = $this->model
->where($filter_w)
->where($where)
->order($sort, $order)
->limit($offset, $limit)->fetchSql(false)
->select();
foreach ($list as $row) {
$row->hidden(['content']);
}
$result = array("total" => $total, "rows" => $list);
$this->success('', $result);
}
/**
* 日志详情
* @ApiParams (name="ids", type="int", required=true, description="日志ID")
*/
public function detail($ids = NULL)
{
$ids = $ids ? $ids : $this->request->param("ids");
$row = $this->model->get(['id' => $ids]);
if (!$row) {
$this->error(__('No Results were found'));
}
$this->success('', $row->toArray());
}
}
... ...