ResourceController.cs 307 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317
  1. using Aspose.Cells;
  2. using Aspose.Words;
  3. using Aspose.Words.Tables;
  4. using EyeSoft.Extensions;
  5. using Microsoft.AspNetCore.Http.Features;
  6. using Newtonsoft.Json.Serialization;
  7. using NodaTime;
  8. using NPOI.SS.Formula.Functions;
  9. using NPOI.SS.UserModel;
  10. using OASystem.API.OAMethodLib;
  11. using OASystem.API.OAMethodLib.HunYuanAPI;
  12. using OASystem.API.OAMethodLib.QiYeWeChatAPI;
  13. using OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice;
  14. using OASystem.Domain.AesEncryption;
  15. using OASystem.Domain.Dtos.Groups;
  16. using OASystem.Domain.Entities.Groups;
  17. using OASystem.Domain.ViewModels.Groups;
  18. using OASystem.Domain.ViewModels.QiYeWeChat;
  19. using OASystem.Infrastructure.Repositories.Groups;
  20. using Quartz.Logging;
  21. using Quartz.Util;
  22. using System.ComponentModel.DataAnnotations;
  23. using System.Data;
  24. using System.Diagnostics;
  25. using TencentCloud.Common;
  26. using static NodaTime.TimeZones.TzdbZone1970Location;
  27. using static OASystem.API.OAMethodLib.GeneralMethod;
  28. using static OASystem.API.OAMethodLib.JWTHelper;
  29. using static OpenAI.GPT3.ObjectModels.Models;
  30. namespace OASystem.API.Controllers
  31. {
  32. /// <summary>
  33. /// 资料相关
  34. /// </summary>
  35. //[Authorize]
  36. [Route("api/[controller]/[action]")]
  37. public class ResourceController : ControllerBase
  38. {
  39. private readonly IMapper _mapper;
  40. private readonly ILogger<ResourceController> _logger;
  41. private readonly IConfiguration _config;
  42. private readonly IHunyuanService _hunyuanService;
  43. private readonly IQiYeWeChatApiService _qiYeWeChatApiService;
  44. private readonly SqlSugarClient _sqlSugar;
  45. private readonly CarDataRepository _carDataRep;
  46. private readonly LocalGuideDataRepository _localGuideDataRep;
  47. private readonly ThreeCodeRepository _ThreeCodeRep;
  48. private readonly HotelDataRepository _hotelDataRep;
  49. private readonly ResItemInfoRepository _resItemInfoRep;
  50. private readonly SetDataRepository _setDataRepository;
  51. private readonly CountryFeeRepository _countryFeeRep;
  52. private readonly SetDataTypeRepository _setDataTypeRep;
  53. private readonly AirTicketAgentRepository _airTicketAgentRep;
  54. private readonly InvitationOfficialActivityDataRepository _InvitationOfficialActivityDataRep;
  55. private readonly OfficialActivitiesRepository _officialActivitiesRep;
  56. private readonly AskDataRepository _askDataRep;
  57. private readonly TicketBlackCodeRepository _ticketBlackCodeRep;
  58. private readonly TourClientListRepository _tourClientListRep;
  59. private readonly DelegationInfoRepository _delegationInfoRep;
  60. private readonly TranslatorLibraryRepository _translatorRep;
  61. private readonly MediaSuppliersRepository _mediaSupplierRep;
  62. private readonly List<int> _portIds;
  63. private readonly BasicInsuranceCostRepository _insuranceCostRep;
  64. private readonly GamesBudgetMasterRepository _gamesBudgetMasterRep;
  65. private readonly OverseaVehicleRepository _overseaVehicleRep;
  66. private readonly MaterialCostRepository _materialCostRep;
  67. /// <summary>
  68. /// 签证费用归属省份静态数据
  69. /// </summary>
  70. private static readonly List<KeyValuePair<int, string>> _provinceData = new()
  71. {
  72. new(122, "四川"),
  73. new(132, "云南"),
  74. new(103, "重庆"),
  75. new(108, "贵州")
  76. };
  77. public ResourceController(
  78. IMapper mapper,
  79. IConfiguration config,
  80. ILogger<ResourceController> logger,
  81. IHunyuanService hunyuanService,
  82. IQiYeWeChatApiService qiYeWeChatApiService,
  83. SqlSugarClient sqlSugar,
  84. CarDataRepository carDataRep,
  85. LocalGuideDataRepository localGuideDataRep,
  86. ThreeCodeRepository threeCodeRep,
  87. HotelDataRepository hotelDataRep,
  88. ResItemInfoRepository resItemInfoRep,
  89. SetDataRepository setDataRepository,
  90. CountryFeeRepository countryFeeRep,
  91. SetDataTypeRepository setDataTypeRep,
  92. AirTicketAgentRepository airTicketAgentRep,
  93. InvitationOfficialActivityDataRepository invitationOfficialActivityDataRep,
  94. OfficialActivitiesRepository officialActivitiesRep,
  95. AskDataRepository askDataRep,
  96. TicketBlackCodeRepository ticketBlackCodeRep,
  97. TourClientListRepository tourClientListRep,
  98. DelegationInfoRepository delegationInfoRep,
  99. TranslatorLibraryRepository translatorRep,
  100. MediaSuppliersRepository mediaSupplierRep,
  101. BasicInsuranceCostRepository insuranceCostRep,
  102. GamesBudgetMasterRepository gamesBudgetMasterRep,
  103. OverseaVehicleRepository overseaVehicleRep,
  104. MaterialCostRepository materialCostRep
  105. )
  106. {
  107. _mapper = mapper;
  108. _config = config;
  109. _logger = logger;
  110. _hunyuanService = hunyuanService;
  111. _qiYeWeChatApiService = qiYeWeChatApiService;
  112. _sqlSugar = sqlSugar;
  113. _carDataRep = carDataRep;
  114. _localGuideDataRep = localGuideDataRep;
  115. _ThreeCodeRep = threeCodeRep;
  116. _hotelDataRep = hotelDataRep;
  117. _resItemInfoRep = resItemInfoRep;
  118. _setDataRepository = setDataRepository;
  119. _countryFeeRep = countryFeeRep;
  120. _setDataTypeRep = setDataTypeRep;
  121. _airTicketAgentRep = airTicketAgentRep;
  122. _InvitationOfficialActivityDataRep = invitationOfficialActivityDataRep;
  123. _officialActivitiesRep = officialActivitiesRep;
  124. _askDataRep = askDataRep;
  125. _ticketBlackCodeRep = ticketBlackCodeRep;
  126. _tourClientListRep = tourClientListRep;
  127. _delegationInfoRep = delegationInfoRep;
  128. _translatorRep = translatorRep;
  129. _mediaSupplierRep = mediaSupplierRep;
  130. _portIds = new List<int> { 1, 2, 3 };
  131. _insuranceCostRep = insuranceCostRep;
  132. _gamesBudgetMasterRep = gamesBudgetMasterRep;
  133. _overseaVehicleRep = overseaVehicleRep;
  134. _materialCostRep = materialCostRep;
  135. }
  136. #region 车公司资料板块
  137. /// <summary>
  138. /// 车公司信息查询
  139. /// </summary>
  140. /// <returns></returns>
  141. [HttpPost]
  142. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  143. public async Task<IActionResult> QueryCarData(QueryCarDataDto dto)
  144. {
  145. Result LocalGuide = await _carDataRep.QueryCarData(dto);
  146. if (LocalGuide.Code == 0)
  147. {
  148. return Ok(JsonView(true, "查询成功", LocalGuide.Data));
  149. }
  150. else
  151. {
  152. return Ok(JsonView(false, LocalGuide.Msg));
  153. }
  154. }
  155. /// <summary>
  156. /// 车公司资料下拉框数据
  157. /// </summary>
  158. /// <returns></returns>
  159. [HttpPost]
  160. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  161. public async Task<IActionResult> QueryCarSelect()
  162. {
  163. var carData = _carDataRep.QueryDto<Res_CarData, CarDataSelectView>().ToList();
  164. if (carData.Count == 0)
  165. {
  166. return Ok(JsonView(false, "暂无数据!"));
  167. }
  168. foreach (var item in carData) EncryptionProcessor.DecryptProperties(item);
  169. carData.Add(new CarDataSelectView { Id = 0, UnitArea = "全部" });
  170. carData = carData.Where((x, i) => carData.FindIndex(z => z.UnitArea == x.UnitArea) == i).ToList();
  171. carData = carData.OrderBy(x => x.Id).ToList();
  172. var data = new List<CarDataSelectView>();
  173. foreach (CarDataSelectView car in carData)
  174. {
  175. if (!string.IsNullOrWhiteSpace(car.UnitArea))
  176. {
  177. data.Add(car);
  178. }
  179. }
  180. return Ok(JsonView(true, "查询成功", data));
  181. }
  182. /// <summary>
  183. /// 根据Id查询车公司详细数据
  184. /// </summary>
  185. /// <returns></returns>
  186. [HttpPost]
  187. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  188. public async Task<IActionResult> QuerCarDataDetailById(QueryCarDataDetailDto dto)
  189. {
  190. string sql = string.Format(@" Select * From Res_CarData With(Nolock) Where Id = {0} ", dto.Id);
  191. var info = _resItemInfoRep._sqlSugar.SqlQueryable<CarDataDetailDataView>(sql).First();
  192. if (info == null)
  193. {
  194. return Ok(JsonView(false, "未找到相关数据!"));
  195. }
  196. EncryptionProcessor.DecryptProperties(info);
  197. return Ok(JsonView(true, "查询成功", info));
  198. }
  199. /// <summary>
  200. /// 车公司信息添加
  201. /// </summary>
  202. /// <returns></returns>
  203. [HttpPost]
  204. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  205. public async Task<IActionResult> AddCarData(AddCarDataDto dto)
  206. {
  207. if (string.IsNullOrEmpty(dto.UnitArea)) return Ok(JsonView(false, "请检查单位区域是否填写!"));
  208. if (string.IsNullOrEmpty(dto.UnitName)) return Ok(JsonView(false, "请检查单位名称是否填写!"));
  209. if (string.IsNullOrEmpty(dto.Contact)) return Ok(JsonView(false, "请检查单位联系人是否填写!"));
  210. if (string.IsNullOrEmpty(dto.ContactTel)) return Ok(JsonView(false, "请检查联系方式是否填写正确!"));
  211. var carDadaInfo = _carDataRep
  212. .QueryDto<Res_CarData, CarDataView>(a => a.UnitArea == dto.UnitArea &&
  213. a.UnitName == dto.UnitName &&
  214. a.Contact == dto.Contact &&
  215. a.ContactTel == dto.ContactTel
  216. )
  217. .First();
  218. if (carDadaInfo != null) return Ok(JsonView(false, "该信息已存在,请勿重复添加!"));
  219. var carData = _mapper.Map<Res_CarData>(dto);
  220. carData.LastUpdateUserId = dto.CreateUserId;
  221. carData.LastUpdateTime = DateTime.Now;
  222. EncryptionProcessor.EncryptProperties(carData);
  223. int id = await _carDataRep.AddAsyncReturnId(carData);
  224. if (id < 1) return Ok(JsonView(false, "添加失败!"));
  225. return Ok(JsonView(true, "添加成功", new { Id = id }));
  226. }
  227. /// <summary>
  228. /// 车公司信息修改
  229. /// </summary>
  230. /// <returns></returns>
  231. [HttpPost]
  232. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  233. public async Task<IActionResult> UpCarData(UpCarDataDto dto)
  234. {
  235. if (string.IsNullOrEmpty(dto.UnitArea)) return Ok(JsonView(false, "请检查单位区域是否填写!"));
  236. if (string.IsNullOrEmpty(dto.UnitName)) return Ok(JsonView(false, "请检查单位名称是否填写!"));
  237. if (string.IsNullOrEmpty(dto.Contact)) return Ok(JsonView(false, "请检查单位联系人是否填写!"));
  238. if (string.IsNullOrEmpty(dto.ContactTel)) return Ok(JsonView(false, "请检查联系方式是否填写正确!"));
  239. var carData = _mapper.Map<Res_CarData>(dto);
  240. carData.LastUpdateTime = DateTime.Now;
  241. EncryptionProcessor.EncryptProperties(carData);
  242. var res = await _sqlSugar.Updateable(carData)
  243. .IgnoreColumns(x => new { x.CreateUserId, x.CreateTime, x.DeleteTime, x.DeleteUserId, x.IsDel })
  244. .ExecuteCommandAsync();
  245. if (res < 1) { return Ok(JsonView(false, "修改失败!")); }
  246. return Ok(JsonView(true, "修改成功"));
  247. }
  248. /// <summary>
  249. /// 车公司信息删除
  250. /// </summary>
  251. /// <returns></returns>
  252. [HttpPost]
  253. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  254. public async Task<IActionResult> DelCarData(DelCarDataDto dto)
  255. {
  256. bool res = await _carDataRep.SoftDeleteByIdAsync<Res_CarData>(dto.Id.ToString(), dto.DeleteUserId);
  257. if (!res) { return Ok(JsonView(false, "删除失败!")); }
  258. return Ok(JsonView(true, "删除成功"));
  259. }
  260. #endregion
  261. #region 导游地接资料板块
  262. [HttpPost]
  263. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  264. public async Task<IActionResult> LocalGuideBatchEncryption()
  265. {
  266. var infos = await _sqlSugar.Queryable<Res_LocalGuideData>().ToListAsync();
  267. foreach (var item in infos) EncryptionProcessor.EncryptProperties(item);
  268. await _sqlSugar.Updateable(infos).ExecuteCommandAsync();
  269. return Ok(JsonView(true));
  270. }
  271. /// <summary>
  272. /// 导游地接资料查询
  273. /// </summary>
  274. /// <param name="dto"></param>
  275. /// <returns></returns>
  276. [HttpPost]
  277. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  278. public async Task<IActionResult> QueryLocalGuide(QueryLocalGuide dto)
  279. {
  280. Stopwatch stopwatch = Stopwatch.StartNew();
  281. Result LocalGuide = await _localGuideDataRep.QueryLocalGuide(dto);
  282. if (LocalGuide.Code == 0)
  283. {
  284. stopwatch.Stop();
  285. return Ok(JsonView(true, $"查询成功!耗时:{stopwatch.ElapsedMilliseconds} 毫秒", LocalGuide.Data));
  286. }
  287. stopwatch.Stop();
  288. return Ok(JsonView(false, LocalGuide.Msg + $" 耗时:{stopwatch.ElapsedMilliseconds} 毫秒"));
  289. }
  290. /// <summary>
  291. /// 导游地接资料下拉框数据
  292. /// </summary>
  293. /// <returns></returns>
  294. [HttpPost]
  295. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  296. public async Task<IActionResult> QueryLocalGuideSelect()
  297. {
  298. var localGuides = _carDataRep.QueryDto<Res_LocalGuideData, QueryLocalGuideSelectView>().ToList();
  299. if (localGuides.Count == 0)
  300. {
  301. return Ok(JsonView(false, "暂无数据!"));
  302. }
  303. foreach (var item in localGuides) EncryptionProcessor.DecryptProperties(item);
  304. localGuides.Add(new QueryLocalGuideSelectView { Id = 0, UnitArea = "全部" });
  305. localGuides = localGuides.Where((x, i) => localGuides.FindIndex(z => z.UnitArea == x.UnitArea && !string.IsNullOrEmpty(z.UnitArea)) == i).ToList();
  306. localGuides = localGuides.OrderBy(x => x.Id).ToList();
  307. var data = new List<QueryLocalGuideSelectView>();
  308. foreach (QueryLocalGuideSelectView Local in localGuides)
  309. {
  310. if (!string.IsNullOrWhiteSpace(Local.UnitArea))
  311. {
  312. data.Add(Local);
  313. }
  314. }
  315. return Ok(JsonView(true, "查询成功", data));
  316. }
  317. /// <summary>
  318. /// 根据Id查询地接详细数据
  319. /// </summary>
  320. /// <returns></returns>
  321. [HttpPost]
  322. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  323. public async Task<IActionResult> QueryLocalGuideDetailById(QueryLocalGuideDetailDto dto)
  324. {
  325. string sql = string.Format(@" Select * From Res_LocalGuideData With(Nolock) Where Id = {0} ", dto.Id);
  326. var info = _resItemInfoRep._sqlSugar.SqlQueryable<LocalGuideDetailDataView>(sql).First();
  327. if (info == null)
  328. {
  329. return Ok(JsonView(false, "未找到相关数据!"));
  330. }
  331. EncryptionProcessor.DecryptProperties(info);
  332. return Ok(JsonView(true, "查询成功", info));
  333. }
  334. /// <summary>
  335. /// 导游地接信息操作(Status:1.新增,2.修改)
  336. /// </summary>
  337. /// <returns></returns>
  338. [HttpPost]
  339. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  340. public async Task<IActionResult> OperationLocalGuide(LocalGuideOperationDto dto)
  341. {
  342. if (string.IsNullOrEmpty(dto.UnitArea)) return Ok(JsonView(false, "请检查单位区域是否填写!"));
  343. if (string.IsNullOrEmpty(dto.UnitName)) return Ok(JsonView(false, "请检查单位名称是否填写!"));
  344. if (string.IsNullOrEmpty(dto.Contact)) return Ok(JsonView(false, "请检查单位联系人是否填写!"));
  345. if (string.IsNullOrEmpty(dto.ContactTel)) return Ok(JsonView(false, "请检查联系方式是否填写正确!"));
  346. Result result = await _localGuideDataRep.LocalGuideOperation(dto);
  347. if (result.Code != 0)
  348. {
  349. return Ok(JsonView(false, result.Msg));
  350. }
  351. return Ok(JsonView(true, result.Msg));
  352. }
  353. /// <summary>
  354. /// 导游地接信息操作(删除)
  355. /// </summary>
  356. /// <returns></returns>
  357. [HttpPost]
  358. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  359. public async Task<IActionResult> DelLocalGuide(LocalGuideDelDto dto)
  360. {
  361. var res = await _localGuideDataRep.SoftDeleteByIdAsync<Res_LocalGuideData>(dto.Id.ToString(), dto.DeleteUserId);
  362. if (!res)
  363. {
  364. return Ok(JsonView(false, "删除失败"));
  365. }
  366. return Ok(JsonView(true, "删除成功!"));
  367. }
  368. #endregion
  369. #region 机场三字码信息
  370. /// <summary>
  371. /// 机场三字码查询
  372. /// </summary>
  373. /// <param name="dto"></param>
  374. /// <returns></returns>
  375. [HttpPost]
  376. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  377. public async Task<IActionResult> QueryThreeCode(QueryThreeCodeDto dto)
  378. {
  379. try
  380. {
  381. Result LocalGuide = await _ThreeCodeRep.QueryThreeCode(dto);
  382. if (LocalGuide.Code == 0)
  383. {
  384. return Ok(JsonView(true, "查询成功", LocalGuide.Data));
  385. }
  386. else
  387. {
  388. return Ok(JsonView(false, LocalGuide.Msg));
  389. }
  390. }
  391. catch (Exception ex)
  392. {
  393. return Ok(JsonView(false, "程序错误!"));
  394. throw;
  395. }
  396. }
  397. /// <summary>
  398. /// 机场三字码数据城市下拉框数据
  399. /// </summary>
  400. /// <returns></returns>
  401. [HttpPost]
  402. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  403. public async Task<IActionResult> QueryThreeCodeSelect()
  404. {
  405. try
  406. {
  407. var ThreeCode = _carDataRep.QueryDto<Res_ThreeCode, ThreeCodeSelectView>().ToList();
  408. if (ThreeCode.Count == 0)
  409. {
  410. return Ok(JsonView(false, "暂无数据!"));
  411. }
  412. ThreeCode.Add(new ThreeCodeSelectView { Id = 0, City = "全部" });
  413. ThreeCode = ThreeCode.Where((x, i) => ThreeCode.FindIndex(z => z.City == x.City && z.City != "") == i).ToList();
  414. ThreeCode = ThreeCode.OrderBy(x => x.Id).ToList();
  415. List<ThreeCodeSelectView> data = new List<ThreeCodeSelectView>();
  416. foreach (ThreeCodeSelectView _ThreeCode in ThreeCode)
  417. {
  418. if (!string.IsNullOrWhiteSpace(_ThreeCode.City))
  419. {
  420. data.Add(_ThreeCode);
  421. }
  422. }
  423. return Ok(JsonView(true, "查询成功", data));
  424. }
  425. catch (Exception)
  426. {
  427. return Ok(JsonView(false, "程序错误!"));
  428. throw;
  429. }
  430. }
  431. /// <summary>
  432. /// 机场三字码资料操作(Status:1.新增,2.修改)
  433. /// </summary>
  434. /// <param name="dto"></param>
  435. /// <returns></returns>
  436. [HttpPost]
  437. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  438. public async Task<IActionResult> OperationThreeCode(ThreeCodeOperationDto dto)
  439. {
  440. try
  441. {
  442. if (dto.Three == "")
  443. {
  444. return Ok(JsonView(false, "请检查三字码是否填写!"));
  445. }
  446. if (dto.Country == "")
  447. {
  448. return Ok(JsonView(false, "请检查国家是否填写!"));
  449. }
  450. if (dto.City == "")
  451. {
  452. return Ok(JsonView(false, "请检查城市是否填写正确!"));
  453. }
  454. if (dto.AirPort == "")
  455. {
  456. return Ok(JsonView(false, "请检查机场是否填写正确!"));
  457. }
  458. Result result = await _ThreeCodeRep.ThreeCodeOperation(dto);
  459. if (result.Code != 0)
  460. {
  461. return Ok(JsonView(false, result.Msg));
  462. }
  463. return Ok(JsonView(true, result.Msg));
  464. }
  465. catch (Exception ex)
  466. {
  467. return Ok(JsonView(false, "程序错误!"));
  468. throw;
  469. }
  470. }
  471. /// <summary>
  472. /// 机场三字码资料操作(删除)
  473. /// </summary>
  474. /// <returns></returns>
  475. [HttpPost]
  476. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  477. public async Task<IActionResult> DelThreeCode(ThreeCodeDelDto dto)
  478. {
  479. try
  480. {
  481. var res = await _ThreeCodeRep.SoftDeleteByIdAsync<Res_ThreeCode>(dto.Id.ToString(), dto.DeleteUserId);
  482. if (!res)
  483. {
  484. return Ok(JsonView(false, "删除失败"));
  485. }
  486. return Ok(JsonView(true, "删除成功!"));
  487. }
  488. catch (Exception ex)
  489. {
  490. return Ok(JsonView(false, "程序错误!"));
  491. throw;
  492. }
  493. }
  494. /// <summary>
  495. ///根据ID查询三字码信息
  496. /// </summary>
  497. /// <returns></returns>
  498. [HttpPost]
  499. public IActionResult QuerySingleThreeCode(QuerySingleThreeCode dto)
  500. {
  501. var jw = JsonView(false);
  502. var single = _sqlSugar.Queryable<Res_ThreeCode>().First(x => x.Id == dto.ID && x.IsDel == 0);
  503. if (single != null)
  504. {
  505. jw = JsonView(true, "获取成功!", new
  506. {
  507. single.Three,
  508. Four = single.Four?.Trim(),
  509. single.AirPort,
  510. single.AirPort_En,
  511. single.City,
  512. single.Country,
  513. single.Remark
  514. });
  515. }
  516. else
  517. {
  518. jw.Msg = "暂无!";
  519. }
  520. return Ok(jw);
  521. }
  522. #endregion
  523. #region 代理出票合作方资料
  524. /// <summary>
  525. /// 代理出票合作方资料
  526. /// </summary>
  527. /// <param name="dto"></param>
  528. /// <returns></returns>
  529. [HttpPost]
  530. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  531. public async Task<IActionResult> QueryAirTicketAgent(DtoBase dto)
  532. {
  533. var res_AirTicketAgents = _airTicketAgentRep.Query<Res_AirTicketAgent>(a => a.IsDel == 0).ToList();
  534. if (res_AirTicketAgents.Count > 1)
  535. {
  536. res_AirTicketAgents = res_AirTicketAgents.OrderByDescending(a => a.CreateTime).ToList();
  537. if (dto.PageSize == 0 && dto.PageIndex == 0)
  538. {
  539. foreach (var item in res_AirTicketAgents) EncryptionProcessor.DecryptProperties(item);
  540. return Ok(JsonView(true, "查询成功!", res_AirTicketAgents));
  541. }
  542. else
  543. {
  544. int count = res_AirTicketAgents.Count;
  545. float totalPage = (float)count / dto.PageSize;//总页数
  546. if (totalPage == 0) totalPage = 1;
  547. else totalPage = (int)Math.Ceiling((double)totalPage);
  548. var _AirTicketAgent = new List<Res_AirTicketAgent>();
  549. for (int i = 0; i < dto.PageSize; i++)
  550. {
  551. var RowIndex = i + (dto.PageIndex - 1) * dto.PageSize;
  552. if (RowIndex < res_AirTicketAgents.Count)
  553. {
  554. EncryptionProcessor.DecryptProperties(res_AirTicketAgents[RowIndex]);
  555. _AirTicketAgent.Add(res_AirTicketAgents[RowIndex]);
  556. }
  557. else break;
  558. }
  559. return Ok(JsonView(true, "查询成功!", new { pageCount = count, totalPage = (int)totalPage, pageIndex = dto.PageIndex, pageSize = dto.PageSize, pageSource = _AirTicketAgent }));
  560. }
  561. }
  562. return Ok(JsonView(false, "暂无数据!"));
  563. }
  564. /// <summary>
  565. /// 代理出票合作方资料操作(Status:1.新增,2.修改)
  566. /// </summary>
  567. /// <param name="dto"></param>
  568. /// <returns></returns>
  569. [HttpPost]
  570. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  571. public async Task<IActionResult> OpAirTicketAgent(OpAirTicketAgentDto dto)
  572. {
  573. if (string.IsNullOrEmpty(dto.Account)) return Ok(JsonView(false, "请检查代理商账户是否填写!"));
  574. if (string.IsNullOrEmpty(dto.Bank)) return Ok(JsonView(false, "请检查代理商银行是否填写!"));
  575. if (string.IsNullOrEmpty(dto.Name)) return Ok(JsonView(false, "请检查代理商名称是否填写正确!"));
  576. Result result = await _airTicketAgentRep.OpAirTicketAgent(dto);
  577. if (result.Code != 0) return Ok(JsonView(false, result.Msg));
  578. return Ok(JsonView(true, result.Msg));
  579. }
  580. /// <summary>
  581. /// 代理出票合作方资料操作(删除)
  582. /// </summary>
  583. /// <returns></returns>
  584. [HttpPost]
  585. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  586. public async Task<IActionResult> DelAirTicketAgent(DelBaseDto dto)
  587. {
  588. var res = await _airTicketAgentRep.SoftDeleteByIdAsync<Res_AirTicketAgent>(dto.Id.ToString(), dto.DeleteUserId);
  589. if (!res) return Ok(JsonView(false, "删除失败"));
  590. return Ok(JsonView(true, "删除成功!"));
  591. }
  592. #endregion
  593. #region 酒店资料数据
  594. /// <summary>
  595. /// 酒店信息查询 Page
  596. /// </summary>
  597. /// <param name="dto"></param>
  598. /// <returns></returns>
  599. [HttpPost]
  600. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  601. public async Task<IActionResult> QueryHotelData(QueryHotelDataDto dto)
  602. {
  603. string sqlWhere = string.Empty;
  604. if (!string.IsNullOrWhiteSpace(dto.Name))
  605. {
  606. sqlWhere += string.Format(@" And hd.Name like '%{0}%'", AesEncryptionHelper.Encrypt(dto.Name));
  607. }
  608. if (!string.IsNullOrWhiteSpace(dto.City) && dto.City != "全部")
  609. {
  610. sqlWhere += string.Format(@" And hd.City like '%{0}%'", AesEncryptionHelper.Encrypt(dto.City));
  611. }
  612. if (!string.IsNullOrWhiteSpace(dto.Contact))
  613. {
  614. sqlWhere += string.Format(@" And hd.Contact like '%{0}%'", AesEncryptionHelper.Encrypt(dto.Contact));
  615. }
  616. if (!string.IsNullOrWhiteSpace(dto.ContactPhone))
  617. {
  618. sqlWhere += string.Format(@" And hd.ContactPhone like '%{0}%'", AesEncryptionHelper.Encrypt(dto.ContactPhone));
  619. }
  620. sqlWhere += string.Format(@" And hd.IsDel={0}", 0);
  621. if (!string.IsNullOrEmpty(sqlWhere.Trim()))
  622. {
  623. Regex r = new Regex("And");
  624. sqlWhere = r.Replace(sqlWhere, "Where", 1);
  625. }
  626. string sql = string.Format(@"SELECT
  627. *
  628. FROM
  629. (
  630. SELECT
  631. ROW_NUMBER() OVER (
  632. ORDER BY
  633. hd.CreateTime DESC
  634. ) AS Row_Number,
  635. hd.Id,
  636. hd.City,
  637. hd.[Name],
  638. hd.Tel,
  639. hd.Fax,
  640. hd.Contact,
  641. hd.ContactPhone,
  642. u.CnName AS CreateUserName,
  643. hd.CreateTime
  644. FROM
  645. Res_HotelData hd
  646. WITH
  647. (NoLock)
  648. LEFT JOIN Sys_Users u
  649. WITH
  650. (NoLock) ON hd.CreateUserId = u.Id {0}
  651. ) Temp
  652. ", sqlWhere);
  653. if (dto.PortType == 1)
  654. {
  655. var HotelDataData = await _sqlSugar.SqlQueryable<HotelDataItemView>(sql).ToListAsync();
  656. if (HotelDataData.Count == 0)
  657. {
  658. return Ok(JsonView(false, "暂无数据"));
  659. }
  660. foreach (var item in HotelDataData)
  661. {
  662. EncryptionProcessor.DecryptProperties(item);
  663. }
  664. return Ok(JsonView(true, "操作成功", HotelDataData));
  665. }
  666. else if (dto.PortType == 2 || dto.PortType == 3)
  667. {
  668. RefAsync<int> total = 0;//REF和OUT不支持异步,想要真的异步这是最优解
  669. var data = await _sqlSugar.SqlQueryable<HotelDataItemView>(sql).ToPageListAsync(dto.PageIndex, dto.PageSize, total); //ToPageAsync
  670. foreach (var item in data) EncryptionProcessor.DecryptProperties(item);
  671. return Ok(JsonView(true, "操作成功", data, total));
  672. }
  673. else return Ok(JsonView(false, "请传入PortType参数!1:Web,2:Android,3:IOS"));
  674. }
  675. /// <summary>
  676. /// 酒店资料
  677. /// 详情
  678. /// add time:2024-05-14 11:57:10
  679. /// </summary>
  680. /// <returns></returns>
  681. [HttpPost]
  682. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  683. public async Task<IActionResult> QueryHotelDataInfo(QueryHotelDataInfoDto dto)
  684. {
  685. var _view = await _hotelDataRep._Info(dto.PortType, dto.Id);
  686. if (_view.Code == 0)
  687. {
  688. return Ok(JsonView(true, _view.Msg, _view.Data));
  689. }
  690. return Ok(JsonView(false, _view.Msg));
  691. }
  692. /// <summary>
  693. /// 酒店资料下拉框数据
  694. /// </summary>
  695. /// <returns></returns>
  696. [HttpPost]
  697. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  698. public async Task<IActionResult> QueryHotelDataSelect()
  699. {
  700. try
  701. {
  702. var HotelData = _carDataRep.QueryDto<Res_HotelData, QueryHotelDataSelect>().ToList();
  703. if (HotelData.Count == 0)
  704. {
  705. return Ok(JsonView(false, "暂无数据!"));
  706. }
  707. //解密
  708. foreach (var item in HotelData)
  709. {
  710. EncryptionProcessor.DecryptProperties(item);
  711. }
  712. HotelData.Add(new QueryHotelDataSelect { Id = 0, City = "全部" });
  713. HotelData = HotelData.Where((x, i) => HotelData.FindIndex(z => z.City == x.City && z.City != "") == i).ToList();
  714. HotelData = HotelData.OrderBy(x => x.Id).ToList();
  715. var data = new List<QueryHotelDataSelect>();
  716. foreach (var Hotel in HotelData)
  717. {
  718. if (!string.IsNullOrWhiteSpace(Hotel.City))
  719. {
  720. data.Add(Hotel);
  721. }
  722. }
  723. return Ok(JsonView(true, "查询成功", data));
  724. }
  725. catch (Exception)
  726. {
  727. return Ok(JsonView(false, "程序错误!"));
  728. throw;
  729. }
  730. }
  731. /// <summary>
  732. /// 酒店资料操作(Status:1.新增,2.修改)
  733. /// </summary>
  734. /// <param name="dto"></param>
  735. /// <returns></returns>
  736. [HttpPost]
  737. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  738. public async Task<IActionResult> OperationHotelData(OperationHotelDto dto)
  739. {
  740. if (string.IsNullOrEmpty(dto.City)) return Ok(JsonView(false, "请检查酒店所在城市是否填写!"));
  741. if (string.IsNullOrEmpty(dto.Name)) return Ok(JsonView(false, "请检查酒店名称是否填写!"));
  742. if (string.IsNullOrEmpty(dto.Address)) return Ok(JsonView(false, "请检查酒店地址是否填写正确!"));
  743. if (string.IsNullOrEmpty(dto.Tel)) return Ok(JsonView(false, "请检查酒店联系方式是否填写正确!"));
  744. Result result = await _hotelDataRep.OperationHotelData(dto);
  745. if (result.Code != 0) return Ok(JsonView(false, result.Msg));
  746. return Ok(JsonView(true, result.Msg));
  747. }
  748. /// <summary>
  749. /// 酒店资料操作(删除)
  750. /// </summary>
  751. /// <returns></returns>
  752. [HttpPost]
  753. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  754. public async Task<IActionResult> DelHotelData(DelHotelDataDto dto)
  755. {
  756. try
  757. {
  758. var res = await _hotelDataRep.SoftDeleteByIdAsync<Res_HotelData>(dto.Id.ToString(), dto.DeleteUserId);
  759. if (!res)
  760. {
  761. return Ok(JsonView(false, "删除失败"));
  762. }
  763. return Ok(JsonView(true, "删除成功!"));
  764. }
  765. catch (Exception ex)
  766. {
  767. return Ok(JsonView(false, "程序错误!"));
  768. throw;
  769. }
  770. }
  771. #endregion
  772. #region 签证费用资料
  773. /// <summary>
  774. /// 签证费用资料查询
  775. /// </summary>
  776. /// <param name="dto"></param>
  777. /// <returns></returns>
  778. [HttpPost]
  779. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  780. public async Task<IActionResult> QueryCountryFeeCost(DtoBase dto)
  781. {
  782. var portType = dto.PortType;
  783. if (portType != 1 && portType != 2 && portType != 3)
  784. return Ok(JsonView(false, "请传入PortType参数!1:Web,2:Android,3:IOS"));
  785. var countryVisaFees = await _countryFeeRep
  786. .QueryDto<Res_CountryFeeCost, CountryFeeCostView>()
  787. .OrderByDescending(x => x.CreateTime)
  788. .ToListAsync();
  789. if (countryVisaFees == null || countryVisaFees.Count == 0)
  790. return Ok(JsonView(false, "暂无数据!"));
  791. return Ok(JsonView(true, "查询成功", countryVisaFees));
  792. }
  793. /// <summary>
  794. /// 签证费用资料查询 Page New
  795. /// </summary>
  796. /// <param name="dto"></param>
  797. /// <returns></returns>
  798. [HttpPost]
  799. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  800. public async Task<IActionResult> QueryVisaCountryFeeCosts(QueryVisaCountryFeeCostsDto dto)
  801. {
  802. // 校验端口类型
  803. if (dto.PortType != 1 && dto.PortType != 2 && dto.PortType != 3)
  804. return Ok(JsonView(false, "请传入PortType参数!1:Web,2:Android,3:IOS"));
  805. var portType = dto.PortType;
  806. RefAsync<int> total = 0;
  807. var query = _countryFeeRep._sqlSugar
  808. .Queryable<Res_CountryFeeCost>()
  809. .Where(x => x.IsDel == 0)
  810. .WhereIF(dto.VisaFeeType >= 0, x => x.VisaFeeType == dto.VisaFeeType)
  811. .WhereIF(!string.IsNullOrEmpty(dto.CountryName), x => x.VisaCountry.Contains(dto.CountryName))
  812. .OrderByDescending(x => x.CreateTime);
  813. var countryVisaFees = await query.ToPageListAsync(dto.PageIndex, dto.PageSize, total);
  814. if (!countryVisaFees.Any()) return Ok(JsonView(true, "暂无数据!"));
  815. var view = _mapper.Map<List<CountryFeeCostView>>(countryVisaFees);
  816. return Ok(JsonView(true, "查询成功", view, total));
  817. }
  818. /// <summary>
  819. /// 签证费用资料操作(Status:1.新增,2.修改)
  820. /// </summary>
  821. /// <param name="dto"></param>
  822. /// <returns></returns>
  823. [HttpPost]
  824. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  825. public async Task<IActionResult> OperationCountryFeeCost(OperationCountryFeeCostDto dto)
  826. {
  827. if (string.IsNullOrWhiteSpace(dto.VisaContinent) || string.IsNullOrWhiteSpace(dto.VisaCountry))
  828. return Ok(JsonView(false, "请检查州名和国家名是否填写!"));
  829. return Ok(await _countryFeeRep.OperationCountryFeeCost(dto));
  830. }
  831. /// <summary>
  832. /// 签证费用资料操作(删除)
  833. /// </summary>
  834. /// <returns></returns>
  835. [HttpPost]
  836. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  837. public async Task<IActionResult> DelCountryFeeCost(DelCountryFeeCostDto dto)
  838. {
  839. var res = await _countryFeeRep.SoftDeleteByIdAsync<Res_CountryFeeCost>(dto.Id.ToString(), dto.DeleteUserId);
  840. if (!res) return Ok(JsonView(false, "删除失败"));
  841. return Ok(JsonView(true, "删除成功!"));
  842. }
  843. #endregion
  844. #region 签证费用资料 New
  845. /// <summary>
  846. /// 签证费用标准 Init
  847. /// </summary>
  848. /// <returns></returns>
  849. [HttpPost]
  850. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  851. public async Task<IActionResult> VisaFeeStandardInit()
  852. {
  853. //签证费用类型数据
  854. var visaFeeTypeData = new List<KeyValuePair<int, string>>
  855. {
  856. new(0, "因公"),
  857. new(1, "因私")
  858. };
  859. //签证费用归属省份
  860. var data = new
  861. {
  862. VisaFeeType = visaFeeTypeData.Select(x => new { Id = x.Key, Text = x.Value }),
  863. Province = _provinceData.Select(x => new { Id = x.Key, Text = x.Value })
  864. };
  865. return Ok(JsonView(data));
  866. }
  867. /// <summary>
  868. /// 签证费用标准 Info
  869. /// </summary>
  870. /// <param name="dto"></param>
  871. /// <returns></returns>
  872. [HttpPost]
  873. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  874. public async Task<IActionResult> VisaFeeStandardInfo(VisaFeeStandardInfoDto dto)
  875. {
  876. var portType = dto.PortType;
  877. if (portType != 1 && portType != 2 && portType != 3)
  878. return Ok(JsonView(false, "请传入PortType参数!1:Web,2:Android,3:IOS"));
  879. return Ok(await _countryFeeRep.InfoAsync(dto.Id));
  880. }
  881. /// <summary>
  882. /// 签证费用标准 List
  883. /// </summary>
  884. /// <param name="dto"></param>
  885. /// <returns></returns>
  886. [HttpPost]
  887. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  888. public async Task<IActionResult> VisaFeeStandardList(VisaFeeStandardListDto dto)
  889. {
  890. return Ok(await _countryFeeRep.PageListAsync(dto));
  891. }
  892. /// <summary>
  893. /// 签证费用标准 Save
  894. /// </summary>
  895. /// <param name="dto"></param>
  896. /// <returns></returns>
  897. [HttpPost]
  898. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  899. public async Task<IActionResult> VisaFeeStandardSave(VisaFeeStandardSaveDto dto)
  900. {
  901. return Ok(await _countryFeeRep.SaveAsync(dto));
  902. }
  903. /// <summary>
  904. /// 签证费用标准 SoftDel
  905. /// </summary>
  906. /// <param name="dto"></param>
  907. /// <returns></returns>
  908. [HttpPost]
  909. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  910. public async Task<IActionResult> VisaFeeStandardSoftDel(VisaFeeStandardSoftDelDto dto)
  911. {
  912. return Ok(await _countryFeeRep.SoftDelAsync(dto.CurrUserId, dto.Id));
  913. }
  914. /// <summary>
  915. /// 根据省份获取签证费用报价
  916. /// </summary>
  917. /// <param name="dto"></param>
  918. /// <returns></returns>
  919. [HttpPost]
  920. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  921. public async Task<IActionResult> VisaFeeQuoteByProvince(VisaFeesByProvinceDto dto)
  922. {
  923. //省份验证
  924. var provinceIds = _provinceData.Select(x => x.Key).ToList();
  925. if (!provinceIds.Contains(dto.ProvinceId))
  926. {
  927. return Ok(JsonView(false, "请选择有效的省份!"));
  928. }
  929. return Ok(await _countryFeeRep.VisaFeeQuoteAsync(dto.ProvinceId, dto.CountryName));
  930. }
  931. #endregion
  932. #region 物料信息、供应商维护
  933. #region 供应商
  934. /// <summary>
  935. /// 物料供应商查询
  936. /// </summary>
  937. /// <param name="_jsonDto">Json序列化</param>
  938. /// <returns></returns>
  939. [HttpPost]
  940. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  941. public async Task<IActionResult> PostSearchItemVendor(JsonDtoBase _jsonDto)
  942. {
  943. if (string.IsNullOrEmpty(_jsonDto.Paras))
  944. {
  945. return Ok(JsonView(false, "参数为空"));
  946. }
  947. Search_ResItemVendorDto _ItemVendorDto = System.Text.Json.JsonSerializer.Deserialize<Search_ResItemVendorDto>(_jsonDto.Paras);
  948. if (_ItemVendorDto != null)
  949. {
  950. if (_ItemVendorDto.SearchType == 2) //获取列表
  951. {
  952. Res_ItemVendorListView rstList = _resItemInfoRep.GetVendorList(_ItemVendorDto);
  953. return Ok(rstList);
  954. }
  955. else
  956. {
  957. Res_ItemVendorView rstInfo = _resItemInfoRep.getVendorInfo(_ItemVendorDto);
  958. return Ok(rstInfo);
  959. }
  960. }
  961. else
  962. {
  963. return Ok(JsonView(false, "参数反序列化失败"));
  964. }
  965. //return Ok(JsonView(false));
  966. }
  967. /// <summary>
  968. /// 创建/编辑/删除供应商信息
  969. /// </summary>
  970. /// <param name="_dto"></param>
  971. /// <returns></returns>
  972. [HttpPost]
  973. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  974. public async Task<IActionResult> PostEditItemVendor(Edit_ResItemVendorDto _dto)
  975. {
  976. bool rst = false;
  977. if (_dto.EditType >= 0)
  978. {
  979. if (string.IsNullOrEmpty(_dto.VendorFullName))
  980. {
  981. return Ok(JsonView(false, "全称未填写"));
  982. }
  983. if (string.IsNullOrEmpty(_dto.VendorLinker))
  984. {
  985. return Ok(JsonView(false, "联系人未填写"));
  986. }
  987. if (string.IsNullOrEmpty(_dto.VendorMobile))
  988. {
  989. return Ok(JsonView(false, "联系人手机号未填写"));
  990. }
  991. if (string.IsNullOrEmpty(_dto.BusRange))
  992. {
  993. return Ok(JsonView(false, "经营范围未选择"));
  994. }
  995. if (_dto.EditType == 0)
  996. {
  997. var checkEmpty = _resItemInfoRep.Query<Res_ItemVendor>(s => s.FullName == _dto.VendorFullName).First();
  998. if (checkEmpty != null)
  999. {
  1000. return Ok(JsonView(false, "已存在同名供应商"));
  1001. }
  1002. rst = await _resItemInfoRep.addVendorInfo(_dto);
  1003. }
  1004. else if (_dto.EditType == 1)
  1005. {
  1006. if (_dto.VendorId > 0)
  1007. {
  1008. Res_ItemVendor _entity = _mapper.Map<Res_ItemVendor>(_dto);
  1009. rst = await _resItemInfoRep.updVendorInfo(_entity);
  1010. }
  1011. else
  1012. {
  1013. return Ok(JsonView(false, "供应商不存在"));
  1014. }
  1015. }
  1016. }
  1017. else
  1018. {
  1019. if (_dto.VendorId < 1 || _dto.SysUserId < 1)
  1020. {
  1021. return Ok(JsonView(false, "用户Id或供应商Id不存在"));
  1022. }
  1023. Res_ItemVendor _entity = _mapper.Map<Res_ItemVendor>(_dto);
  1024. rst = await _resItemInfoRep.delVendorInfo(_entity);
  1025. }
  1026. return Ok(JsonView(rst));
  1027. }
  1028. #endregion
  1029. #region 物料信息
  1030. /// <summary>
  1031. /// 物料信息查询
  1032. /// </summary>
  1033. /// <param name="paras">Json序列化</param>
  1034. /// <returns></returns>
  1035. [HttpPost]
  1036. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1037. public async Task<IActionResult> PostSearchItemInfo(string paras)
  1038. {
  1039. if (string.IsNullOrEmpty(paras))
  1040. {
  1041. return Ok(JsonView(false, "参数为空"));
  1042. }
  1043. Search_ItemInfoDto _ItemInfoDto = System.Text.Json.JsonSerializer.Deserialize<Search_ItemInfoDto>(paras);
  1044. if (_ItemInfoDto != null)
  1045. {
  1046. if (_ItemInfoDto.SearchType == 2) //获取列表
  1047. {
  1048. Res_ItemInfoListView rstList = _resItemInfoRep.GetItemList(_ItemInfoDto);
  1049. return Ok(rstList);
  1050. }
  1051. else
  1052. {
  1053. Res_ItemInfoView rstInfo = _resItemInfoRep.getItemInfo(_ItemInfoDto);
  1054. return Ok(rstInfo);
  1055. }
  1056. }
  1057. else
  1058. {
  1059. return Ok(JsonView(false, "参数反序列化失败"));
  1060. }
  1061. //return Ok(JsonView(false));
  1062. }
  1063. /// <summary>
  1064. /// 创建/编辑/删除物料信息
  1065. /// </summary>
  1066. ///
  1067. /// <returns></returns>
  1068. [HttpPost]
  1069. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1070. public async Task<IActionResult> PostEditItemInfo(Edit_ResItemInfoDto _dto)
  1071. {
  1072. bool rst = false;
  1073. if (_dto.EditType >= 0)
  1074. {
  1075. if (_dto.VendorId < 1)
  1076. {
  1077. return Ok(JsonView(false, "未选择供应商"));
  1078. }
  1079. if (string.IsNullOrEmpty(_dto.ItemName))
  1080. {
  1081. return Ok(JsonView(false, "物料名称为空"));
  1082. }
  1083. if (_dto.ItemTypeId < 1)
  1084. {
  1085. return Ok(JsonView(false, "未选择物料类型"));
  1086. }
  1087. if (_dto.SysUserId < 1)
  1088. {
  1089. return Ok(JsonView(false, "当前操作用户Id为空"));
  1090. }
  1091. if (_dto.CurrRate <= 0)
  1092. {
  1093. return Ok(JsonView(false, "物料录入价格不能小于等于0"));
  1094. }
  1095. if (_dto.EditType == 0)
  1096. {
  1097. //判断物料名称、类型、供应商全部重复
  1098. var checkEmpty = _resItemInfoRep.Query<Res_ItemDetailInfo>(s => s.ItemName == _dto.ItemName && s.ItemTypeId == _dto.ItemTypeId && s.VendorId == _dto.VendorId).First();
  1099. if (checkEmpty != null)
  1100. {
  1101. return Ok(JsonView(false, "已存在重复物料信息"));
  1102. }
  1103. Res_ItemDetailInfo _entity = _mapper.Map<Res_ItemDetailInfo>(_dto);
  1104. DateTime dtNow = DateTime.Now;
  1105. _entity.CreateUserId = _dto.SysUserId;
  1106. _entity.IsDel = 0;
  1107. _entity.MaxRate = _dto.CurrRate;
  1108. _entity.MaxDt = dtNow;
  1109. _entity.CurrRate = _dto.CurrRate;
  1110. _entity.CurrDt = dtNow;
  1111. _entity.MinRate = _dto.CurrRate;
  1112. _entity.MinDt = dtNow;
  1113. rst = await _resItemInfoRep.AddAsync<Res_ItemDetailInfo>(_entity) > 0;
  1114. }
  1115. else if (_dto.EditType == 1)
  1116. {
  1117. if (_dto.ItemId > 0)
  1118. {
  1119. Res_ItemDetailInfo _entity = _mapper.Map<Res_ItemDetailInfo>(_dto);
  1120. _entity.Id = _dto.ItemId;
  1121. rst = await _resItemInfoRep.updItemInfo(_entity);
  1122. }
  1123. else
  1124. {
  1125. return Ok(JsonView(false, "供应商不存在"));
  1126. }
  1127. }
  1128. }
  1129. else
  1130. {
  1131. if (_dto.ItemId < 1 || _dto.SysUserId < 1)
  1132. {
  1133. return Ok(JsonView(false, "用户Id或物料信息Id不存在"));
  1134. }
  1135. Res_ItemDetailInfo _entity = _mapper.Map<Res_ItemDetailInfo>(_dto);
  1136. rst = await _resItemInfoRep.delItemInfo(_entity);
  1137. }
  1138. return Ok(JsonView(rst));
  1139. }
  1140. #endregion
  1141. #region 物料类型获取
  1142. #endregion
  1143. #endregion
  1144. #region 备忘录
  1145. /// <summary>
  1146. /// 备忘录查询
  1147. /// </summary>
  1148. /// <param name="_jsonDto">Json序列化</param>
  1149. /// <returns></returns>
  1150. [HttpPost]
  1151. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1152. public async Task<IActionResult> PostSearchMemo(JsonDtoBase _jsonDto)
  1153. {
  1154. if (string.IsNullOrEmpty(_jsonDto.Paras))
  1155. {
  1156. return Ok(JsonView(false, "参数为空"));
  1157. }
  1158. Search_ResMemoDto _memoDto = JsonConvert.DeserializeObject<Search_ResMemoDto>(_jsonDto.Paras);
  1159. if (_memoDto != null)
  1160. {
  1161. if (_memoDto.SearchType == 2)
  1162. {
  1163. //获取列表
  1164. string sqlWhere = string.Format(" Where IsDel=0 ");
  1165. #region SqlWhere
  1166. if (!string.IsNullOrEmpty(_memoDto.Abstracts))
  1167. {
  1168. sqlWhere += string.Format(@" And m.Abstracts Like '%{0}%' ", _memoDto.Abstracts);
  1169. }
  1170. if (!string.IsNullOrEmpty(_memoDto.Title))
  1171. {
  1172. sqlWhere += string.Format(@" And m.Title Like '%{0}%' ", _memoDto.Title);
  1173. }
  1174. if (_memoDto.ReadLevel > 0)
  1175. {
  1176. sqlWhere += string.Format(@" And m.ReadLevel = {0} ", _memoDto.ReadLevel);
  1177. }
  1178. #endregion
  1179. int currPIndex = (((_memoDto.PageIndex > 0) ? (_memoDto.PageIndex - 1) : 0) * _memoDto.PageSize) + 1;
  1180. int currPSize = (((_memoDto.PageIndex > 0) ? (_memoDto.PageIndex - 1) : 0) + 1) * _memoDto.PageSize;
  1181. string sql = string.Format(@" Select * From(Select ROW_NUMBER() Over(order By m.Id desc) as RowNumber,
  1182. m.Id as MemoId,d.DepName as DepartmentName,m.ReadLevel,m.Title,m.Abstracts,
  1183. m.LastedEditDt,m.LastedEditorId
  1184. From Res_Memo as m With(Nolock) Inner Join Sys_Users as u With(Nolock) On m.CreateUserId=u.Id
  1185. Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id {2}
  1186. ) as tb Where tb.RowNumber Between {0} And {1} ", currPIndex, currPSize, sqlWhere);
  1187. Res_MemoListView rst = new Res_MemoListView();
  1188. rst.CurrPageIndex = currPIndex;
  1189. rst.CurrPageSize = currPSize;
  1190. List<Res_MemoView> dataSource = _carDataRep._sqlSugar.SqlQueryable<Res_MemoView>(sql).ToList();
  1191. Dictionary<int, string> userDic = new Dictionary<int, string>();
  1192. foreach (var item in dataSource)
  1193. {
  1194. if (userDic.ContainsKey(item.LastedEditorId))
  1195. {
  1196. item.LastedEditor = userDic[item.LastedEditorId];
  1197. }
  1198. else
  1199. {
  1200. var _sysUser = _carDataRep.Query<Sys_Users>(s => s.Id == item.LastedEditorId).First();
  1201. userDic[item.LastedEditorId] = _sysUser.CnName;
  1202. item.LastedEditor = _sysUser.CnName;
  1203. }
  1204. }
  1205. rst.DataList = new List<Res_MemoView>(dataSource);
  1206. if (rst.DataList.Count > 0)
  1207. {
  1208. string sqlCount = string.Format(@" Select Id From Res_Memo as m With(Nolock) {0} ", sqlWhere);
  1209. int dataCount = _carDataRep._sqlSugar.SqlQueryable<Res_MemoInfo>(sqlCount).Count();
  1210. rst.DataCount = dataCount;
  1211. }
  1212. return Ok(JsonView(rst));
  1213. }
  1214. else
  1215. {
  1216. //获取对象
  1217. string sqlSingle = string.Format(@" Select
  1218. m.Id as MemoId,d.DepName as DepartmentName,m.ReadLevel,m.Title,m.Abstracts,
  1219. m.LastedEditDt,m.LastedEditor,m.MDFilePath
  1220. From Res_Memo as m With(Nolock) Inner Join Sys_Users as u With(Nolock) On m.CreateUserId=u.Id
  1221. Inner Join Sys_Department as d With(Nolock) On u.DepId=d.Id Where m.Id={0} ", _memoDto.MemoId);
  1222. Res_MemoView _result = _carDataRep._sqlSugar.SqlQueryable<Res_MemoView>(sqlSingle).First();
  1223. if (_result != null)
  1224. {
  1225. var _sysUser = _carDataRep.Query<Sys_Users>(s => s.Id == _result.LastedEditorId).First();
  1226. _result.LastedEditor = _sysUser.CnName;
  1227. _result.MarkDownContent = new IOOperatorHelper().Read(_result.MDFilePath);
  1228. return Ok(JsonView(_result));
  1229. }
  1230. }
  1231. }
  1232. else
  1233. {
  1234. return Ok(JsonView(false, "参数反序列化失败"));
  1235. }
  1236. return Ok(JsonView(false));
  1237. }
  1238. /// <summary>
  1239. /// 创建/编辑/删除备忘录信息
  1240. /// </summary>
  1241. /// <param name="_dto"></param>
  1242. /// <returns></returns>
  1243. [HttpPost]
  1244. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1245. public async Task<IActionResult> PostEditMemo(Edit_ResMemoDto _dto)
  1246. {
  1247. bool rst = false;
  1248. if (_dto.SysUserId < 1)
  1249. {
  1250. return Ok(JsonView(false, "操作人失效"));
  1251. }
  1252. var _sysUser = _resItemInfoRep.Query<Sys_Users>(s => s.Id == _dto.SysUserId).First();
  1253. if (_sysUser == null)
  1254. {
  1255. return Ok(JsonView(false, "操作人失效02"));
  1256. }
  1257. if (_dto.EditType >= 0)
  1258. {
  1259. if (_dto.ReadLevel < 1)
  1260. {
  1261. return Ok(JsonView(false, "未知的阅读等级"));
  1262. }
  1263. if (string.IsNullOrEmpty(_dto.Title.Trim()))
  1264. {
  1265. return Ok(JsonView(false, "标题不能为空"));
  1266. }
  1267. if (string.IsNullOrEmpty(_dto.Content.Trim()))
  1268. {
  1269. return Ok(JsonView(false, "正文内容不能为空"));
  1270. }
  1271. //新增备忘录
  1272. DateTime dtNow = DateTime.Now;
  1273. string dir = AppSettingsHelper.Get("MemoCurrPath");
  1274. string fileName = dtNow.ToString("yyyyMMddHHmmss") + _dto.Title + ".md";
  1275. string content = JsonConvert.SerializeObject(_dto.Content);
  1276. if (_dto.EditType == 0)//新增
  1277. {
  1278. string savePath = new IOOperatorHelper().Write_CoverFile(content, dir, fileName);
  1279. if (savePath.Length > 0)
  1280. {
  1281. Res_MemoInfo _insert = new Res_MemoInfo();
  1282. _insert.Abstracts = _dto.Abstracts;
  1283. _insert.Title = _dto.Title;
  1284. _insert.DepartmentId = _sysUser.DepId;
  1285. _insert.CreateUserId = _sysUser.Id;
  1286. _insert.LastedEditDt = dtNow;
  1287. _insert.LastedEditor = _sysUser.Id;
  1288. _insert.MDFilePath = savePath;
  1289. _insert.ReadLevel = _dto.ReadLevel;
  1290. _insert.Title = _dto.Title;
  1291. int result = await _resItemInfoRep.AddAsync(_insert);
  1292. return Ok(JsonView(result > 0));
  1293. }
  1294. else
  1295. {
  1296. return Ok(JsonView(false, "路径保存失败"));
  1297. }
  1298. }
  1299. else//修改
  1300. {
  1301. if (_dto.MemoId < 1)
  1302. {
  1303. return Ok(JsonView(false, "MemoId不存在"));
  1304. }
  1305. Res_MemoInfo _source = _resItemInfoRep.Query<Res_MemoInfo>(s => s.Id == _dto.MemoId).First();
  1306. if (_source == null)
  1307. {
  1308. return Ok(JsonView(false, "MemoInfo不存在"));
  1309. }
  1310. //修改
  1311. string sourcePath = _source.MDFilePath;
  1312. string recycDir = AppSettingsHelper.Get("MemoRecycleBinPath");
  1313. new IOOperatorHelper().MoveFile(sourcePath, recycDir);
  1314. string savePath = new IOOperatorHelper().Write_CoverFile(content, dir, fileName);
  1315. if (savePath.Length > 0)
  1316. {
  1317. var result = await _resItemInfoRep._sqlSugar.Updateable<Res_MemoInfo>()
  1318. .SetColumns(it => it.LastedEditDt == DateTime.Now)
  1319. .SetColumns(it => it.LastedEditor == _sysUser.Id)
  1320. .SetColumns(it => it.Abstracts == _dto.Abstracts)
  1321. .SetColumns(it => it.MDFilePath == savePath)
  1322. .SetColumns(it => it.ReadLevel == _dto.ReadLevel)
  1323. .SetColumns(it => it.Title == _dto.Title)
  1324. .Where(s => s.Id == _source.Id)
  1325. .ExecuteCommandAsync();
  1326. return Ok(JsonView(result > 0));
  1327. }
  1328. }
  1329. }
  1330. else
  1331. {
  1332. //删除
  1333. if (_dto.MemoId < 1)
  1334. {
  1335. return Ok(JsonView(false, "MemoId不存在"));
  1336. }
  1337. Res_MemoInfo _source = _resItemInfoRep.Query<Res_MemoInfo>(s => s.Id == _dto.MemoId).First();
  1338. if (_source == null)
  1339. {
  1340. return Ok(JsonView(false, "MemoInfo不存在"));
  1341. }
  1342. //修改
  1343. string sourcePath = _source.MDFilePath;
  1344. string recycDir = AppSettingsHelper.Get("MemoRecycleBinPath");
  1345. new IOOperatorHelper().MoveFile(sourcePath, recycDir);
  1346. var result = await _resItemInfoRep._sqlSugar.Updateable<Res_MemoInfo>()
  1347. .SetColumns(it => it.IsDel == 1)
  1348. .SetColumns(it => it.DeleteUserId == _sysUser.Id)
  1349. .SetColumns(it => it.DeleteTime == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
  1350. .Where(s => s.Id == _source.Id)
  1351. .ExecuteCommandAsync();
  1352. return Ok(JsonView(result > 0));
  1353. }
  1354. return Ok(JsonView(rst));
  1355. }
  1356. #endregion
  1357. #region 商邀资料
  1358. /// <summary>
  1359. /// 商邀资料 基础数据源
  1360. /// </summary>
  1361. /// <param name="dto"></param>
  1362. /// <returns></returns>
  1363. [HttpPost]
  1364. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1365. public async Task<IActionResult> QueryIOAInitData(QueryIOAInitDataDto dto)
  1366. {
  1367. #region 参数验证
  1368. if (dto.PortType < 1) return Ok(JsonView(false, "请传入有效的PortType参数!"));
  1369. #endregion
  1370. var ExcludedKeyStr = new string[] { "快递费" };
  1371. var ClientKeyStr = new string[] { "邀请函翻译" };
  1372. List<Grp_DelegationInfo> _DelegationInfos = _sqlSugar.Queryable<Grp_DelegationInfo>().Where(it => it.IsDel == 0).OrderByDescending(it => it.JietuanTime).ToList();
  1373. List<Res_InvitationOfficialActivityData> _ioaDatas = _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  1374. .Where(it => it.IsDel == 0)
  1375. .Select(x => new Res_InvitationOfficialActivityData
  1376. {
  1377. Country = x.Country,
  1378. UnitName = x.UnitName,
  1379. Contact = x.Contact,
  1380. Field = x.Field,
  1381. })
  1382. .ToList();
  1383. foreach (var item in _ioaDatas)
  1384. {
  1385. EncryptionProcessor.DecryptProperties(item);
  1386. }
  1387. foreach (var item in ExcludedKeyStr)
  1388. {
  1389. _ioaDatas = _ioaDatas.Where(x => string.IsNullOrWhiteSpace(x.UnitName) || !x.UnitName.Contains(item)).ToList();
  1390. }
  1391. foreach (var item in ClientKeyStr)
  1392. {
  1393. _ioaDatas = _ioaDatas.Where(x => string.IsNullOrWhiteSpace(x.Contact) || !x.Contact.Contains(item)).ToList();
  1394. }
  1395. List<Sys_Users> _Users = _sqlSugar.Queryable<Sys_Users>().Where(it => it.IsDel == 0).ToList();
  1396. var _countryData = _ioaDatas.Select(it => it.Country).Distinct().ToList(); _countryData.Remove("");
  1397. var _inviterData = _ioaDatas.Select(it => it.UnitName).Distinct().ToList(); _inviterData.Remove("");
  1398. var _contactData = _ioaDatas.Select(it => it.Contact).Distinct().ToList(); _contactData.Remove("");
  1399. var _domainData = _ioaDatas.Select(it => it.Field).Distinct().ToList(); _domainData.Remove("");
  1400. var _groupNameData = _DelegationInfos.Select(it => new { it.Id, it.TeamName }).ToList();
  1401. var _userNameData = _Users.Select(it => new { it.Id, it.CnName }).ToList();
  1402. var _data = new
  1403. {
  1404. CountryData = _countryData,
  1405. InviterData = _inviterData,
  1406. DomainData = _domainData,
  1407. ContactData = _contactData,
  1408. GroupNameData = _groupNameData,
  1409. UserNameData = _userNameData,
  1410. };
  1411. return Ok(JsonView(true, $"查询成功!", _data));
  1412. }
  1413. /// <summary>
  1414. /// 商邀资料查询
  1415. /// </summary>
  1416. /// <param name="dto"></param>
  1417. /// <returns></returns>
  1418. [HttpPost]
  1419. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1420. public async Task<IActionResult> QueryInvitationOfficialActivityData(QueryInvitationOfficialActivityDataDto dto)
  1421. {
  1422. var ExcludedKeyStr = new string[] { "快递费" };
  1423. var ClientKeyStr = new string[] { "邀请函翻译" };
  1424. var columns = "Id,UnitName,Contact,City";
  1425. try
  1426. {
  1427. #region 参数验证
  1428. if (dto.PageIndex < 1) return Ok(JsonView(false, "请传入有效的PageIndex参数!"));
  1429. if (dto.PageSize < 1) return Ok(JsonView(false, "请传入有效的PageSize参数!"));
  1430. #endregion
  1431. //string sqlWhere = string.Empty;
  1432. if (!string.IsNullOrWhiteSpace(dto.Country)) { columns += ",Country"; }
  1433. //if (!string.IsNullOrWhiteSpace(dto.UnitName)) { columns += ",UnitName"; }
  1434. //if (!string.IsNullOrWhiteSpace(dto.Contact)) { columns += ",Contact"; }
  1435. if (!string.IsNullOrWhiteSpace(dto.Delegation)) { columns += ",Delegation"; }
  1436. if (!string.IsNullOrWhiteSpace(dto.Field)) { columns += ",Field"; }
  1437. //if (dto.CreateUserId != 0 && !string.IsNullOrWhiteSpace(dto.CreateUserId.ToString())) { columns += ",CreateUserId"; }
  1438. //if (!string.IsNullOrWhiteSpace(dto.StartCreateTime) && !string.IsNullOrWhiteSpace(dto.EndCreateTime))
  1439. //{
  1440. // columns += ",CreateUserId";
  1441. //}
  1442. DateTime endTime = new DateTime();
  1443. var InvitationOfficialActivityDataList = _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  1444. .Where(x => x.IsDel == 0)
  1445. .WhereIF(dto.CreateUserId != 0 && !string.IsNullOrWhiteSpace(dto.CreateUserId.ToString()), x => x.CreateUserId == dto.CreateUserId)
  1446. .WhereIF(DateTime.TryParse(dto.StartCreateTime, out DateTime startTime) && DateTime.TryParse(dto.EndCreateTime, out endTime), x => x.CreateTime >= startTime && x.CreateTime <= endTime)
  1447. .Select(columns)
  1448. .ToList();
  1449. foreach (var item in InvitationOfficialActivityDataList)
  1450. {
  1451. EncryptionProcessor.DecryptProperties(item);
  1452. }
  1453. InvitationOfficialActivityDataList = InvitationOfficialActivityDataList
  1454. .WhereIF(!string.IsNullOrWhiteSpace(dto.Country), x => (!string.IsNullOrWhiteSpace(x.Country) && x.Country.Contains(dto.Country)) || (!string.IsNullOrWhiteSpace(x.City) && x.City.Contains(dto.Country)))
  1455. .WhereIF(!string.IsNullOrWhiteSpace(dto.UnitName), x => !string.IsNullOrWhiteSpace(x.UnitName) && x.UnitName.Contains(dto.UnitName))
  1456. .WhereIF(!string.IsNullOrWhiteSpace(dto.Contact), x => !string.IsNullOrWhiteSpace(x.Contact) && x.Contact.Contains(dto.Contact))
  1457. .WhereIF(!string.IsNullOrWhiteSpace(dto.Delegation), x => !string.IsNullOrWhiteSpace(x.Delegation) && x.Delegation.Contains(dto.Delegation))
  1458. .WhereIF(!string.IsNullOrWhiteSpace(dto.Field), x => !string.IsNullOrWhiteSpace(x.Field) && x.Field.Contains(dto.Field))
  1459. .ToList();
  1460. foreach (var item in ExcludedKeyStr)
  1461. {
  1462. InvitationOfficialActivityDataList = InvitationOfficialActivityDataList.Where(x => string.IsNullOrWhiteSpace(x.UnitName) || !x.UnitName.Contains(item)).ToList();
  1463. //sqlWhere += $" And i.UnitName not like '%{item}%' ";
  1464. }
  1465. foreach (var item in ClientKeyStr)
  1466. {
  1467. InvitationOfficialActivityDataList = InvitationOfficialActivityDataList.Where(x => string.IsNullOrWhiteSpace(x.Contact) || !x.Contact.Contains(item)).ToList();
  1468. //sqlWhere += $" And i.Contact not like '%{item}%' ";
  1469. }
  1470. var ids = InvitationOfficialActivityDataList.Select(x => x.Id);
  1471. RefAsync<int> totalCount = 0;
  1472. var _ivitiesViews = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  1473. .LeftJoin<Sys_Users>((a, b) => b.IsDel == 0 && a.CreateUserId == b.Id)
  1474. .Where((a, b) => ids.Contains(a.Id))
  1475. .OrderByDescending((a, b) => a.CreateTime)
  1476. .Select((a, b) => new InvitationOfficialActivityDataView
  1477. {
  1478. FaceBook = a.FaceBook,
  1479. Id = a.Id,
  1480. CreateUserId = a.CreateUserId,
  1481. IsDel = 0,
  1482. Address = a.Address,
  1483. Background = a.Background,
  1484. City = a.City,
  1485. Contact = a.Contact,
  1486. Country = a.Country,
  1487. CreateTime = a.CreateTime,
  1488. CreateUserName = b.CnName,
  1489. Delegation = a.Delegation,
  1490. Email = a.Email,
  1491. Fax = a.Fax,
  1492. Field = a.Field,
  1493. FilePath = a.FilePath,
  1494. Ins = a.Ins,
  1495. WeChat = a.WeChat,
  1496. UnitWeb = a.UnitWeb,
  1497. UnitName = a.UnitName,
  1498. UnitInfo = a.UnitInfo,
  1499. Tel = a.Tel,
  1500. SndFilePath = a.SndFilePath,
  1501. SndFileName = a.SndFileName,
  1502. Remark = a.Remark,
  1503. OtherInfo = a.OtherInfo,
  1504. Job = a.Job
  1505. })
  1506. .ToPageListAsync(dto.PageIndex, dto.PageSize, totalCount);
  1507. var allGroupIds = new HashSet<int>();
  1508. foreach (var item in _ivitiesViews)
  1509. {
  1510. EncryptionProcessor.DecryptProperties(item);
  1511. if (!string.IsNullOrEmpty(item.Delegation))
  1512. {
  1513. allGroupIds.UnionWith(item.Delegation.Split(',').Select(x =>
  1514. {
  1515. int id;
  1516. if (int.TryParse(x, out id)) return id;
  1517. return 0;
  1518. }).Where(id => id != 0));
  1519. }
  1520. }
  1521. var _DelegationInfos = _sqlSugar.Queryable<Grp_DelegationInfo>()
  1522. .Where(x => allGroupIds.Contains(x.Id) && x.IsDel == 0)
  1523. .ToList()
  1524. .GroupBy(x => x.Id)
  1525. .ToDictionary(group => group.Key, group => group.Select(g => g.TeamName));
  1526. foreach (var item in _ivitiesViews)
  1527. {
  1528. string groupNameStr = "";
  1529. if (!string.IsNullOrEmpty(item.Delegation))
  1530. {
  1531. var groupIds = item.Delegation.Split(',').Select(x =>
  1532. {
  1533. int id;
  1534. if (int.TryParse(x, out id)) return id;
  1535. return 0;
  1536. })
  1537. .Where(id => id != 0)
  1538. .ToArray();
  1539. foreach (var id in groupIds)
  1540. {
  1541. if (_DelegationInfos.ContainsKey(id))
  1542. {
  1543. groupNameStr += string.Join("", _DelegationInfos[id]) + ",";
  1544. }
  1545. }
  1546. if (groupNameStr.Length > 1)
  1547. {
  1548. groupNameStr = groupNameStr.Substring(0, groupNameStr.Length - 1);
  1549. }
  1550. }
  1551. item.DelegationStr = groupNameStr;
  1552. }
  1553. return Ok(JsonView(true, $"查询成功!", _ivitiesViews, totalCount));
  1554. }
  1555. catch (Exception ex)
  1556. {
  1557. return Ok(JsonView(false, ex.Message));
  1558. }
  1559. }
  1560. /// <summary>
  1561. /// 商邀资料查询-欧洲
  1562. /// </summary>
  1563. /// <returns></returns>
  1564. [HttpPost]
  1565. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1566. public async Task<IActionResult> QueryInvitationOfficialActivityData1()
  1567. {
  1568. try
  1569. {
  1570. // 定义欧洲国家数组
  1571. string[] europeanCountries = {
  1572. // 北欧国家
  1573. "瑞典", "芬兰", "挪威", "丹麦", "冰岛",
  1574. // 西欧国家
  1575. "英国", "爱尔兰", "法国", "荷兰", "比利时", "卢森堡", "摩纳哥",
  1576. // 中欧国家
  1577. "德国", "瑞士", "奥地利", "波兰", "捷克", "斯洛伐克", "匈牙利", "列支敦士登",
  1578. // 南欧国家
  1579. "意大利", "西班牙", "葡萄牙", "希腊", "马耳他", "圣马力诺", "梵蒂冈", "安道尔",
  1580. "克罗地亚", "斯洛文尼亚", "波斯尼亚和黑塞哥维那", "黑山", "塞尔维亚", "北马其顿", "阿尔巴尼亚", "保加利亚", "罗马尼亚",
  1581. // 东欧国家
  1582. "俄罗斯", "乌克兰", "白俄罗斯", "摩尔多瓦", "爱沙尼亚", "拉脱维亚", "立陶宛"
  1583. };
  1584. var InvitationOfficialActivityDataList = _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  1585. .Where(x => x.IsDel == 0)
  1586. .Select(x => new Res_InvitationOfficialActivityData() { Id = x.Id, Country = x.Country })
  1587. .ToList();
  1588. foreach (var item in InvitationOfficialActivityDataList)
  1589. {
  1590. EncryptionProcessor.DecryptProperties(item);
  1591. }
  1592. var ids = InvitationOfficialActivityDataList
  1593. .WhereIF(europeanCountries.Any(), x => !string.IsNullOrWhiteSpace(x.Country) && europeanCountries.Contains(x.Country))
  1594. .Select(x => x.Id)
  1595. .ToList();
  1596. RefAsync<int> totalCount = 0;
  1597. var _ivitiesViews = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  1598. .LeftJoin<Sys_Users>((a, b) => b.IsDel == 0 && a.CreateUserId == b.Id)
  1599. .Where((a, b) => ids.Contains(a.Id))
  1600. .OrderByDescending((a, b) => a.CreateTime)
  1601. .Select((a, b) => new InvitationOfficialActivityDataView1
  1602. {
  1603. Country = a.Country,
  1604. City = a.City,
  1605. UnitName = a.UnitName,
  1606. Field = a.Field,
  1607. Address = a.Address,
  1608. UnitInfo = a.UnitInfo,
  1609. Delegation = a.Delegation,
  1610. OtherInfo = a.OtherInfo
  1611. })
  1612. .ToListAsync();
  1613. var allGroupIds = new HashSet<int>();
  1614. foreach (var item in _ivitiesViews)
  1615. {
  1616. EncryptionProcessor.DecryptProperties(item);
  1617. if (!string.IsNullOrEmpty(item.Delegation))
  1618. {
  1619. allGroupIds.UnionWith(item.Delegation.Split(',').Select(x =>
  1620. {
  1621. int id;
  1622. if (int.TryParse(x, out id)) return id;
  1623. return 0;
  1624. }).Where(id => id != 0));
  1625. }
  1626. }
  1627. var _DelegationInfos = _sqlSugar.Queryable<Grp_DelegationInfo>()
  1628. .Where(x => allGroupIds.Contains(x.Id) && x.IsDel == 0)
  1629. .ToList()
  1630. .GroupBy(x => x.Id)
  1631. .ToDictionary(group => group.Key, group => group.Select(g => g.TeamName));
  1632. foreach (var item in _ivitiesViews)
  1633. {
  1634. string groupNameStr = "";
  1635. if (!string.IsNullOrEmpty(item.Delegation))
  1636. {
  1637. var groupIds = item.Delegation.Split(',').Select(x =>
  1638. {
  1639. int id;
  1640. if (int.TryParse(x, out id)) return id;
  1641. return 0;
  1642. })
  1643. .Where(id => id != 0)
  1644. .ToArray();
  1645. foreach (var id in groupIds)
  1646. {
  1647. if (_DelegationInfos.ContainsKey(id))
  1648. {
  1649. groupNameStr += string.Join("", _DelegationInfos[id]) + ",";
  1650. }
  1651. }
  1652. if (groupNameStr.Length > 1)
  1653. {
  1654. groupNameStr = groupNameStr.Substring(0, groupNameStr.Length - 1);
  1655. }
  1656. }
  1657. item.DelegationStr = groupNameStr;
  1658. }
  1659. //获取模板
  1660. string tempPath = (AppSettingsHelper.Get("ExcelBasePath") + "Template/商邀资料模板.xls");
  1661. var designer = new WorkbookDesigner();
  1662. designer.Workbook = new Workbook(tempPath);
  1663. var dt = CommonFun.ToDataTableArray(_ivitiesViews);
  1664. dt.TableName = $"OADataView";
  1665. designer.SetDataSource(dt);
  1666. designer.Process();
  1667. //文件名
  1668. string fileName = $"商邀资料{DateTime.Now.ToString("yyyyMMddHHmmss")}.xls";
  1669. designer.Workbook.Save(AppSettingsHelper.Get("ExcelBasePath") + "InvitationOfficialActivityExport/" + fileName);
  1670. string url = AppSettingsHelper.Get("ExcelBaseUrl") + "Office/Excel/InvitationOfficialActivityExport/" + fileName;
  1671. return Ok(JsonView(true, "成功", url));
  1672. }
  1673. catch (Exception ex)
  1674. {
  1675. return Ok(JsonView(false, ex.Message));
  1676. }
  1677. }
  1678. //[HttpPost]
  1679. //public IActionResult EncipherInvitationOfficialActivityData()
  1680. //{
  1681. // var jw = JsonView(false);
  1682. // var List_DB = _sqlSugar.Queryable<Res_InvitationOfficialActivityData>().ToList();
  1683. // try
  1684. // {
  1685. // //foreach (var item in List_DB)
  1686. // //{
  1687. // // EncryptionProcessor.DecryptProperties(item);
  1688. // //}
  1689. // _sqlSugar.BeginTran();
  1690. // foreach (var item in List_DB)
  1691. // {
  1692. // EncryptionProcessor.EncryptProperties(item);
  1693. // }
  1694. // var updateRow = _sqlSugar.Updateable<Res_InvitationOfficialActivityData>(List_DB).ExecuteCommand();
  1695. // jw = JsonView(true, "success", "修改行数:" + updateRow);
  1696. // _sqlSugar.CommitTran();
  1697. // }
  1698. // catch (Exception ex)
  1699. // {
  1700. // _sqlSugar.RollbackTran();
  1701. // jw.Msg = ex.Message;
  1702. // }
  1703. // return Ok(jw);
  1704. //}
  1705. /// <summary>
  1706. /// 根据商邀资料Id查询信息
  1707. /// </summary>
  1708. /// <param name="id"></param>
  1709. /// <returns></returns>
  1710. [HttpGet("{id}")]
  1711. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1712. public async Task<IActionResult> QueryInvitationOfficialActivityById(int id)
  1713. {
  1714. if (id < 1) return Ok(JsonView(false, "Id参数错误!"));
  1715. return Ok(await _InvitationOfficialActivityDataRep.Info(id));
  1716. }
  1717. /// <summary>
  1718. /// 商邀资料操作(Status:1.新增,2.修改)
  1719. /// </summary>
  1720. /// <param name="dto"></param>
  1721. /// <returns></returns>
  1722. [HttpPost]
  1723. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1724. public async Task<IActionResult> OpInvitationOfficialActivity([FromForm] OpInvitationOfficialActivityDto dto)
  1725. {
  1726. return Ok(await _InvitationOfficialActivityDataRep.IOA_OP(dto));
  1727. }
  1728. /// <summary>
  1729. /// 商邀资料 删除文件
  1730. /// </summary>
  1731. /// <param name="id"></param>
  1732. /// <param name="fileName"></param>
  1733. /// <returns></returns>
  1734. [HttpDelete("{id}")]
  1735. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1736. public async Task<IActionResult> InvitationOfficialActivityDelFile(int id, string fileName)
  1737. {
  1738. if (id < 1) return Ok(JsonView(false, "请传入有效的Id"));
  1739. if (string.IsNullOrEmpty(fileName)) return Ok(JsonView(false, "文件名称不能为空!"));
  1740. var info = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>().FirstAsync(x => x.Id == id);
  1741. if (info == null) return Ok(JsonView(false, "该条数据不存在!"));
  1742. var files = new List<string>();
  1743. try
  1744. {
  1745. files = JsonConvert.DeserializeObject<List<string>>(info.SndFileName);
  1746. }
  1747. catch (Exception) { }
  1748. if (files != null && files.Count > 0 && files.Contains(fileName))
  1749. {
  1750. var filePath = $@"{AppSettingsHelper.Get("GrpFileBasePath")}/商邀相关文件/{fileName}";
  1751. if (System.IO.File.Exists(filePath))
  1752. {
  1753. System.IO.File.Delete(filePath);
  1754. }
  1755. //更改文件值
  1756. files.Remove(fileName);
  1757. var fileUpd = await _sqlSugar.Updateable<Res_InvitationOfficialActivityData>()
  1758. .SetColumns(x => x.SndFileName == JsonConvert.SerializeObject(files))
  1759. .Where(x => x.Id == id)
  1760. .ExecuteCommandAsync();
  1761. if (fileUpd > 0) return Ok(JsonView(true, "操作成功!"));
  1762. }
  1763. return Ok(JsonView(false, "操作失败!"));
  1764. }
  1765. /// <summary>
  1766. /// 删除商邀资料信息
  1767. /// </summary>
  1768. /// <param name="dto"></param>
  1769. /// <returns></returns>
  1770. [HttpPost]
  1771. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1772. public async Task<IActionResult> DelInvitationOfficialActivity(DelBaseDto dto)
  1773. {
  1774. var res = await _InvitationOfficialActivityDataRep.SoftDeleteByIdAsync<Res_InvitationOfficialActivityData>(dto.Id.ToString(), dto.DeleteUserId);
  1775. if (!res) return Ok(JsonView(false, "删除失败"));
  1776. var info = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>().FirstAsync(x => x.Id == dto.Id);
  1777. if (info == null) return Ok(JsonView(false, "该条数据不存在!"));
  1778. var files = new List<string>();
  1779. try
  1780. {
  1781. files = JsonConvert.DeserializeObject<List<string>>(info.SndFileName);
  1782. }
  1783. catch (Exception) { }
  1784. if (files != null && files.Count > 0)
  1785. {
  1786. foreach (var fileName in files)
  1787. {
  1788. var filePath = $@"{AppSettingsHelper.Get("GrpFileBasePath")}/商邀相关文件/{fileName}";
  1789. if (System.IO.File.Exists(filePath))
  1790. {
  1791. System.IO.File.Delete(filePath);
  1792. }
  1793. }
  1794. }
  1795. return Ok(JsonView(true, "删除成功!"));
  1796. }
  1797. /// <summary>
  1798. /// 商邀资料 ExcelExport
  1799. /// </summary>
  1800. /// <param name="dto"></param>
  1801. /// <returns></returns>
  1802. [HttpPost]
  1803. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1804. public async Task<IActionResult> InvitationOfficialActivityExcelExport(QueryInvitationOfficialActivityDataDto dto)
  1805. {
  1806. var ExcludedKeyStr = new string[] { "快递费" };
  1807. var ClientKeyStr = new string[] { "邀请函翻译" };
  1808. var columns = "Id,UnitName,Contact";
  1809. #region 参数验证
  1810. if (dto.PageIndex < 1) return Ok(JsonView(false, "请传入有效的PageIndex参数!"));
  1811. if (dto.PageSize < 1) return Ok(JsonView(false, "请传入有效的PageSize参数!"));
  1812. #endregion
  1813. if (!string.IsNullOrWhiteSpace(dto.Country)) { columns += ",Country"; }
  1814. if (!string.IsNullOrWhiteSpace(dto.Delegation)) { columns += ",Delegation"; }
  1815. if (!string.IsNullOrWhiteSpace(dto.Field)) { columns += ",Field"; }
  1816. DateTime endTime = new DateTime();
  1817. var InvitationOfficialActivityDataList = _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  1818. .Where(x => x.IsDel == 0)
  1819. .WhereIF(dto.CreateUserId != 0 && !string.IsNullOrWhiteSpace(dto.CreateUserId.ToString()), x => x.CreateUserId == dto.CreateUserId)
  1820. .WhereIF(DateTime.TryParse(dto.StartCreateTime, out DateTime startTime) && DateTime.TryParse(dto.EndCreateTime, out endTime), x => x.CreateTime >= startTime && x.CreateTime <= endTime)
  1821. .Select(columns)
  1822. .ToList();
  1823. foreach (var item in InvitationOfficialActivityDataList)
  1824. {
  1825. EncryptionProcessor.DecryptProperties(item);
  1826. }
  1827. InvitationOfficialActivityDataList = InvitationOfficialActivityDataList
  1828. .WhereIF(!string.IsNullOrWhiteSpace(dto.Country), x => !string.IsNullOrWhiteSpace(x.Country) && x.Country.Contains(dto.Country))
  1829. .WhereIF(!string.IsNullOrWhiteSpace(dto.UnitName), x => !string.IsNullOrWhiteSpace(x.UnitName) && x.UnitName.Contains(dto.UnitName))
  1830. .WhereIF(!string.IsNullOrWhiteSpace(dto.Contact), x => !string.IsNullOrWhiteSpace(x.Contact) && x.Contact.Contains(dto.Contact))
  1831. .WhereIF(!string.IsNullOrWhiteSpace(dto.Delegation), x => !string.IsNullOrWhiteSpace(x.Delegation) && x.Delegation.Contains(dto.Delegation))
  1832. .WhereIF(!string.IsNullOrWhiteSpace(dto.Field), x => !string.IsNullOrWhiteSpace(x.Field) && x.Field.Contains(dto.Field))
  1833. .ToList();
  1834. foreach (var item in ExcludedKeyStr)
  1835. {
  1836. InvitationOfficialActivityDataList = InvitationOfficialActivityDataList.Where(x => string.IsNullOrWhiteSpace(x.UnitName) || !x.UnitName.Contains(item)).ToList();
  1837. //sqlWhere += $" And i.UnitName not like '%{item}%' ";
  1838. }
  1839. foreach (var item in ClientKeyStr)
  1840. {
  1841. InvitationOfficialActivityDataList = InvitationOfficialActivityDataList.Where(x => string.IsNullOrWhiteSpace(x.Contact) || !x.Contact.Contains(item)).ToList();
  1842. //sqlWhere += $" And i.Contact not like '%{item}%' ";
  1843. }
  1844. var ids = InvitationOfficialActivityDataList.Select(x => x.Id);
  1845. var _ivitiesViews = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  1846. .LeftJoin<Sys_Users>((a, b) => b.IsDel == 0 && a.CreateUserId == b.Id)
  1847. .Where((a, b) => ids.Contains(a.Id))
  1848. .OrderByDescending((a, b) => a.CreateTime)
  1849. .Select((a, b) => new IOAInfoView
  1850. {
  1851. FaceBook = a.FaceBook,
  1852. Id = a.Id,
  1853. Address = a.Address,
  1854. Background = a.Background,
  1855. City = a.City,
  1856. Contact = a.Contact,
  1857. Country = a.Country,
  1858. Delegation = a.Delegation,
  1859. Email = a.Email,
  1860. Fax = a.Fax,
  1861. Field = a.Field,
  1862. Ins = a.Ins,
  1863. WeChat = a.WeChat,
  1864. UnitWeb = a.UnitWeb,
  1865. UnitName = a.UnitName,
  1866. UnitInfo = a.UnitInfo,
  1867. Tel = a.Tel,
  1868. SndFileName = a.SndFileName,
  1869. Remark = a.Remark,
  1870. OtherInfo = a.OtherInfo,
  1871. Job = a.Job
  1872. })
  1873. .ToListAsync();
  1874. if (!_ivitiesViews.Any()) return Ok(JsonView(false, $"您查询的数据暂无内容,不可导出!"));
  1875. var allGroupIds = new HashSet<int>();
  1876. foreach (var item in _ivitiesViews)
  1877. {
  1878. EncryptionProcessor.DecryptProperties(item);
  1879. if (!string.IsNullOrEmpty(item.Delegation))
  1880. {
  1881. allGroupIds.UnionWith(
  1882. item.Delegation.Split(',')
  1883. .Select(x =>
  1884. {
  1885. int id;
  1886. if (int.TryParse(x, out id)) return id;
  1887. return 0;
  1888. })
  1889. .Where(id => id != 0)
  1890. );
  1891. }
  1892. }
  1893. var _DelegationInfos = _sqlSugar.Queryable<Grp_DelegationInfo>()
  1894. .Where(x => allGroupIds.Contains(x.Id) && x.IsDel == 0)
  1895. .ToList()
  1896. .GroupBy(x => x.Id)
  1897. .ToDictionary(group => group.Key, group => group.Select(g => g.TeamName));
  1898. foreach (var item in _ivitiesViews)
  1899. {
  1900. string groupNameStr = "";
  1901. if (!string.IsNullOrEmpty(item.Delegation))
  1902. {
  1903. var groupIds = item.Delegation.Split(',').Select(x =>
  1904. {
  1905. int id;
  1906. if (int.TryParse(x, out id)) return id;
  1907. return 0;
  1908. })
  1909. .Where(id => id != 0)
  1910. .ToArray();
  1911. foreach (var id in groupIds)
  1912. {
  1913. if (_DelegationInfos.ContainsKey(id))
  1914. {
  1915. groupNameStr += string.Join("", _DelegationInfos[id]) + ",";
  1916. }
  1917. }
  1918. if (groupNameStr.Length > 1)
  1919. {
  1920. groupNameStr = groupNameStr.Substring(0, groupNameStr.Length - 1);
  1921. }
  1922. }
  1923. item.DelegationStr = groupNameStr;
  1924. }
  1925. //获取模板
  1926. string tempPath = (AppSettingsHelper.Get("ExcelBasePath") + "Template/商邀资料模板.xls");
  1927. var designer = new WorkbookDesigner();
  1928. designer.Workbook = new Workbook(tempPath);
  1929. var dt = CommonFun.ToDataTableArray(_ivitiesViews);
  1930. dt.TableName = $"OADataView";
  1931. designer.SetDataSource(dt);
  1932. designer.Process();
  1933. //文件名
  1934. string fileName = $"商邀资料{DateTime.Now.ToString("yyyyMMddHHmmss")}.xls";
  1935. designer.Workbook.Save(AppSettingsHelper.Get("ExcelBasePath") + "InvitationOfficialActivityExport/" + fileName);
  1936. string url = AppSettingsHelper.Get("ExcelBaseUrl") + "Office/Excel/InvitationOfficialActivityExport/" + fileName;
  1937. return Ok(JsonView(true, "成功", url));
  1938. }
  1939. /// <summary>
  1940. /// 商邀资料 导入文件(Excel)模板下载
  1941. /// </summary>
  1942. /// <returns></returns>
  1943. [HttpGet]
  1944. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1945. public async Task<IActionResult> InvitationOfficialActivityExcelTemplateExport()
  1946. {
  1947. //获取模板
  1948. string fileName = $"商邀资料上传文件模板.xls";
  1949. string url = AppSettingsHelper.Get("ExcelBaseUrl") + "Office/Excel/Template/" + fileName;
  1950. return Ok(JsonView(true, "成功", url));
  1951. }
  1952. /// <summary>
  1953. /// 商邀资料 上传Excel文件添加
  1954. /// </summary>
  1955. /// <param name="file"></param>
  1956. /// <param name="currUserId"></param>
  1957. /// <returns></returns>
  1958. [HttpPost]
  1959. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  1960. public async Task<IActionResult> InvitationOfficialActivityExcelUpload(IFormFile file, int currUserId)
  1961. {
  1962. var fileName = file.FileName;
  1963. var filePostfix = fileName.Split(".")[1].ToUpper();
  1964. if (!filePostfix.Contains("XLS")) return Ok(JsonView(false, $"请传入Excel文件"));
  1965. if (file.Length < 1) return Ok(JsonView(false, $"请传入有效的文件"));
  1966. if (currUserId < 1) return Ok(JsonView(false, $"请传入有效的UserId"));
  1967. //保存文件
  1968. string fileDirPath = string.Format(@"{0}InvitationOfficialActivityExcelUpload/", AppSettingsHelper.Get("ExcelBasePath"));
  1969. if (!Directory.Exists(fileDirPath))
  1970. {
  1971. Directory.CreateDirectory(fileDirPath);
  1972. }
  1973. var filePath = Path.Combine(fileDirPath, fileName);
  1974. await using var stream = new FileStream(filePath, FileMode.Create);
  1975. await file.CopyToAsync(stream);
  1976. //读取保存的文件
  1977. Workbook workbook = new Workbook(filePath);
  1978. if (workbook == null) return Ok(JsonView(false, $"Excel文件不存在!"));
  1979. Worksheet worksheet = workbook.Worksheets[0];
  1980. if (worksheet == null) return Ok(JsonView(false, $"Excel文件工作簿不存在!"));
  1981. var infos = new List<Res_InvitationOfficialActivityData>();
  1982. var groupNames = await _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && !string.IsNullOrEmpty(x.TeamName)).Select(x => new { x.Id, x.TeamName }).ToListAsync();
  1983. for (int row = 1; row < worksheet.Cells.MaxDataRow + 1; row++)
  1984. {
  1985. var groupIdsLabel = string.Empty;
  1986. var groupNames1 = worksheet.Cells[row, 14].StringValue ?? "-";
  1987. if (!string.IsNullOrEmpty(groupNames1))
  1988. {
  1989. if (groupNames1.Contains(";"))
  1990. {
  1991. var groupNameArray = groupNames1.Split(";").Where(x => !string.IsNullOrEmpty(x)).ToList();
  1992. var groupIds = groupNames.Where(x => groupNameArray.Contains(x.TeamName)).Select(x => x.Id).ToList();
  1993. if (groupIds.Any()) groupIdsLabel = string.Join(',', groupIds);
  1994. }
  1995. else groupIdsLabel = groupNames.Where(x => groupNames1.Equals(x.TeamName)).FirstOrDefault()?.Id.ToString() ?? string.Empty;
  1996. }
  1997. infos.Add(new Res_InvitationOfficialActivityData()
  1998. {
  1999. Country = worksheet.Cells[row, 0].StringValue ?? "-",
  2000. City = worksheet.Cells[row, 1].StringValue ?? "-",
  2001. UnitName = worksheet.Cells[row, 2].StringValue ?? "-",
  2002. Field = worksheet.Cells[row, 3].StringValue ?? "-",
  2003. Address = worksheet.Cells[row, 4].StringValue ?? "-",
  2004. UnitInfo = worksheet.Cells[row, 5].StringValue ?? "-",
  2005. Contact = worksheet.Cells[row, 6].StringValue ?? "-",
  2006. Job = worksheet.Cells[row, 7].StringValue ?? "-",
  2007. Tel = worksheet.Cells[row, 8].StringValue ?? "-",
  2008. Email = worksheet.Cells[row, 9].StringValue ?? "-",
  2009. WeChat = worksheet.Cells[row, 10].StringValue ?? "-",
  2010. FaceBook = worksheet.Cells[row, 11].StringValue ?? "-",
  2011. Ins = worksheet.Cells[row, 12].StringValue ?? "-",
  2012. Fax = worksheet.Cells[row, 13].StringValue ?? "-",
  2013. Delegation = groupIdsLabel,
  2014. SndFilePath = worksheet.Cells[row, 15].StringValue ?? "-",
  2015. OtherInfo = worksheet.Cells[row, 16].StringValue ?? "-",
  2016. Remark = $"[{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}] Excel上传文件添加! 文件存储地址[{filePath}]",
  2017. CreateUserId = currUserId,
  2018. IsDel = 0
  2019. });
  2020. }
  2021. //加密
  2022. foreach (var item in infos) EncryptionProcessor.EncryptProperties(item);
  2023. var addCount = await _sqlSugar.Insertable(infos).ExecuteCommandAsync();
  2024. if (addCount < 1) return Ok(JsonView(false, "文件上传添加失败!"));
  2025. return Ok(JsonView(true, $"上传文件添加成功!共添加{addCount}条!"));
  2026. }
  2027. #endregion
  2028. #region 商邀资料 AI
  2029. /// <summary>
  2030. /// 商邀资料AI 基础数据源
  2031. /// </summary>
  2032. /// <returns></returns>
  2033. [HttpGet]
  2034. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  2035. public async Task<IActionResult> InvitationAIInit()
  2036. {
  2037. var itemNames = await GeneralMethod.InvitationAIInvName();
  2038. var unitNames = await GeneralMethod.InvitationAIClientName();
  2039. var countries = await GeneralMethod.InvitationAICountryName();
  2040. return Ok(JsonView(true, $"查询成功!", new
  2041. {
  2042. itemNames,
  2043. unitNames,
  2044. countries
  2045. }));
  2046. }
  2047. /// <summary>
  2048. /// 商邀资料AI 资料列表
  2049. /// </summary>
  2050. /// <returns></returns>
  2051. [HttpGet("{name}")]
  2052. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  2053. public async Task<IActionResult> InvitationAIItemByName(string name)
  2054. {
  2055. // 基础校验
  2056. if (string.IsNullOrWhiteSpace(name))
  2057. return Ok(JsonView(false, "请传入有效的名称!"));
  2058. var info = await _sqlSugar.Queryable<Res_InvitationAI>()
  2059. .Where(x => x.IsDel == 0 && x.InvName == name)
  2060. .FirstAsync();
  2061. var groupInfo = new Grp_DelegationInfo();
  2062. if (info == null)
  2063. {
  2064. groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && x.TeamName.Equals(name)).FirstAsync();
  2065. var entry = new EntryInfo() {
  2066. OriginUnit = groupInfo?.ClientUnit ?? "",
  2067. TargetCountry = _delegationInfoRep.GroupSplitCountry(groupInfo?.VisitCountry ?? ""),
  2068. };
  2069. return Ok(JsonView(true, $"暂无数据",new {
  2070. Id = 0,
  2071. GroupId= groupInfo?.Id ?? 0,
  2072. InvName = name,
  2073. AiCrawledDetails = new List<InvitationAIInfo>(),
  2074. Entry = entry
  2075. }));
  2076. }
  2077. if (info.GroupId != 0)
  2078. {
  2079. groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && x.Id == info.GroupId).FirstAsync();
  2080. }
  2081. // 设置国家、单位默认值
  2082. if (string.IsNullOrEmpty(info.EntryInfo.OriginUnit))
  2083. {
  2084. info.EntryInfo.OriginUnit = groupInfo?.ClientUnit ?? "";
  2085. }
  2086. if (info.EntryInfo.TargetCountry == null || info.EntryInfo.TargetCountry.Count < 1)
  2087. {
  2088. info.EntryInfo.TargetCountry = _delegationInfoRep.GroupSplitCountry(groupInfo?.TeamName ?? "");
  2089. }
  2090. var view = new
  2091. {
  2092. info.Id,
  2093. info.GroupId,
  2094. info.InvName,
  2095. info.AiCrawledDetails,
  2096. Entry = info.EntryInfo,
  2097. };
  2098. return Ok(JsonView(true, $"查询成功!", view));
  2099. }
  2100. /// <summary>
  2101. /// 商邀资料AI 混元AI查询资料
  2102. /// </summary>
  2103. /// <returns></returns>
  2104. [HttpPost]
  2105. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  2106. public async Task<IActionResult> InvitationAISearch(InvitationAISearchDto dto)
  2107. {
  2108. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.Id == dto.Id).FirstAsync();
  2109. if (invAiInfo == null || invAiInfo?.EntryInfo == null)
  2110. {
  2111. return Ok(JsonView(false, "请先设置关键字信息!"));
  2112. }
  2113. var entryInfo = invAiInfo.EntryInfo;
  2114. // 当前企业领域
  2115. string industryFocus = string.Empty;
  2116. // 动态计算 AI 需求缺口
  2117. int totalTarget = entryInfo.NeedCount;
  2118. // 词条
  2119. string question = string.Empty;
  2120. string operatorName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
  2121. var localInvDatas = new List<InvitationAIInfo>(); // 本地数据源(商邀资料)
  2122. var aiTasks = new List<CountryAIPormptInfo>(); // 记录:国家 -> 需要补齐的数量
  2123. #region 本地数据源(商邀资料)
  2124. var datas = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  2125. .Where(x => x.IsDel == 0)
  2126. .Select(x => new {
  2127. x.Id,
  2128. x.Country
  2129. })
  2130. .ToListAsync();
  2131. var decryptDatas = new List<Res_InvitationOfficialActivityData>();
  2132. foreach (var item in datas)
  2133. {
  2134. decryptDatas.Add(new() {
  2135. Id = item.Id,
  2136. Country = AesEncryptionHelper.Decrypt(item.Country)
  2137. });
  2138. }
  2139. var localDatas = decryptDatas.Where(x=> !string.IsNullOrEmpty(x.Country) && entryInfo.TargetCountry.Contains(x.Country)).ToList();
  2140. var localDataIds = localDatas.Select(x => x.Id).ToList();
  2141. var rawData = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  2142. .Where(x => localDataIds.Contains(x.Id))
  2143. .ToListAsync();
  2144. // 解密
  2145. var localInvDecryptDatas = rawData.AsParallel().AsOrdered().Select(item => new InvitationAIInfo
  2146. {
  2147. Guid = Guid.NewGuid().ToString("N"),
  2148. Source = 0, // 明确来源标识
  2149. Region = AesEncryptionHelper.Decrypt(item.Country),
  2150. NameCn = AesEncryptionHelper.Decrypt(item.UnitName),
  2151. Address = AesEncryptionHelper.Decrypt(item.Address),
  2152. Scope = AesEncryptionHelper.Decrypt(item.Field),
  2153. Contact = AesEncryptionHelper.Decrypt(item.Contact),
  2154. Phone = AesEncryptionHelper.Decrypt(item.Tel),
  2155. Email = AesEncryptionHelper.Decrypt(item.Email),
  2156. OperatedAt = DateTime.Now,
  2157. Operator = operatorName,
  2158. }).ToList();
  2159. // 国家数据条数
  2160. int targetPerCountry = invAiInfo.EntryInfo?.NeedCount ?? 10;
  2161. foreach (var countryName in invAiInfo.EntryInfo.TargetCountry)
  2162. {
  2163. var countryDatas = localInvDecryptDatas.Where(x => x.Region == countryName).Take(targetPerCountry).ToList();
  2164. if (countryDatas.Any())
  2165. {
  2166. localInvDatas.AddRange(countryDatas);
  2167. int gap = targetPerCountry - countryDatas.Count;
  2168. if (gap > 0) aiTasks.Add(new() { Country = countryName, Count = gap });
  2169. }
  2170. }
  2171. #endregion
  2172. #region 混元AI 获取商邀资料
  2173. var hunyuanAIInvDatas = new List<InvitationAIInfo>();
  2174. if (aiTasks != null && aiTasks.Count > 0)
  2175. {
  2176. question = @$"# [SYSTEM_CONTEXT]
  2177. - Role: Senior Business Consultant (Global Supply Chain & Cross-border Trade Expert)
  2178. - Framework: S.P.A.R. (Situation-Problem-Action-Result)
  2179. - Target Architecture: .NET 6 DTO Compatible Interface
  2180. # [INPUT_CONFIG]
  2181. - Tasks: {{{JsonConvert.SerializeObject(aiTasks)}}}
  2182. - OriginUnit: {{{entryInfo.OriginUnit}}}
  2183. - Objective: {{{entryInfo.Objective}}}
  2184. - OtherConstraints: {{{entryInfo.OtherConstraints}}}
  2185. # [ROLE_DEFINITION]
  2186. 你是一位精通全球跨境经贸、海外园区政策及 Tasks 中的国家本地准入法规的【顶级商务咨询顾问】。你擅长通过“产业链对等原则(Chain-Parity Principle)”为跨国企业精准匹配具备落地价值的合作伙伴。
  2187. # [BUSINESS_LOGIC_CoT]
  2188. 在生成结果前,请严格执行以下思维链拆解:
  2189. 1. **ScopePartitioning**: 遍历 Tasks 中的每个国家。
  2190. 1. **EntityProfiling**: 识别 {{OriginUnit}} 的核心生态位(如:Supply/Demand/Capital/Logistics)。
  2191. 2. **ParityMatching**: 针对每个国家,检索境内业务闭环对等机构。(例如:若 Origin 为分销,则 Target 为源头工厂/种植园)。
  2192. 3. **RegulatoryCheck**: 验证目标机构的合规性(如:GACC 备案、SPS 协议、或当地政府特许经营权)。
  2193. 4. **DataSynthesis**: 必须严格根据每个国家对应的 Count 生成数据条数。针对无法直接获取的动态(如 PostUrl),优先检索其官网 News 频道或 LinkedIn 企业号。
  2194. # [CONSTRAINTS_&_STANDARDS]
  2195. - **NamingConvention**: 所有 JSON Key 必须严格遵循 **PascalCase**(例如:`UnitNameCn` 而非 `unit_name_cn`)。
  2196. - **DataIntegrity**:
  2197. - 总条数必须等于 Tasks 中所有 Count 的总和。
  2198. - 优先级:Core (核心机构) > Backup (关联替代机构)。
  2199. - **ValidationRules**:
  2200. - `Phone`: 必须包含 Tasks 中的国家国际区号(如 +856, +66 等)。
  2201. - `IntgAdvice`: 必须包含“对等性分析”,解释该机构如何与 {{OriginUnit}} 形成业务闭环(50-100字)。
  2202. - `Status`: 若字段确实无法获取,统一填充 'N/A',禁止编造。
  2203. - **Safety**: 确保推荐机构不涉及敏感黑名单或已破产企业。
  2204. # [INFORMATION_SCHEMA]
  2205. 请将结果填充至以下结构的 JSON 数组中:
  2206. - Region:国家(必须与 Tasks 中的 Country 完全匹配)
  2207. - NameCn: 单位名称(中文)
  2208. - NameEn: 单位名称(英文)
  2209. - Address: 详细地理位置(含省市区街道)
  2210. - Scope: 经营范围(需强调其出口配额、生产能力或行业地位)
  2211. - Contact: 联系人姓名及职务
  2212. - Phone: 拨打全号(含区号)
  2213. - Email: 商务联络邮箱
  2214. - SiteUrl: 官方网站或权威社媒主页
  2215. - PostUrl: 近一年内的商务动态/新闻链接
  2216. - RecLevel: 推荐等级(枚举值:Core, Backup)
  2217. - IntgAdvice: 对接深度建议(基于产业链交合、互补逻辑)
  2218. # [OUTPUT_PROTOCOL]
  2219. - 仅输出一个标准的 JSON Array 字符串。
  2220. - 严禁任何 Markdown 说明文字、代码块之外的解释或开场白。
  2221. - 确保 JSON 语法在 .NET `JsonSerializer.Deserialize` 下可直接解析。
  2222. # [EXECUTION]
  2223. 根据以上配置,开始生成。";
  2224. string response = string.Empty;
  2225. try
  2226. {
  2227. response = await _hunyuanService.ChatCompletionsHunyuan_t1_latestAsync(question);
  2228. }
  2229. catch (HttpRequestException ex)
  2230. {
  2231. _logger.LogError(ex, "网络连接失败,无法调用混元API");
  2232. return Ok(JsonView(false, $"网络连接异常,请检查网络后重试!Ex:{ex.Message}"));
  2233. }
  2234. catch (TaskCanceledException ex)
  2235. {
  2236. _logger.LogError(ex, "请求超时");
  2237. return Ok(JsonView(false, $"AI 响应超时,请稍后再试!Ex:{ex.Message}"));
  2238. }
  2239. catch (TencentCloudSDKException ex)
  2240. {
  2241. // 记录完整日志
  2242. _logger.LogError(ex, "腾讯云API调用失败 | 错误码: {ErrorCode} | 请求ID: {RequestId}", ex.ErrorCode, ex.RequestId);
  2243. // 根据错误码做差异化处理
  2244. if (ex.ErrorCode != null && ex.ErrorCode == "AuthFailure.SignatureExpire")
  2245. {
  2246. return Ok(JsonView(false, $"系统时间异常,请同步时间后重试!Ex:{ex.Message}"));
  2247. }
  2248. else if (ex.ErrorCode != null && ex.ErrorCode.StartsWith("Unauthorized"))
  2249. {
  2250. return Ok(JsonView(false, $"当前账号无权限访问该服务!Ex:{ex.Message}"));
  2251. }
  2252. else
  2253. {
  2254. return Ok(JsonView(false, $"腾讯云服务调用失败,请稍后重试!Ex:{ex.Message}"));
  2255. }
  2256. }
  2257. catch (Exception ex)
  2258. {
  2259. _logger.LogError(ex, "未知错误,调用混元API失败");
  2260. return Ok(JsonView(false, $"未知错误,调用混元API失败!Ex:{ex.Message}"));
  2261. }
  2262. if (!string.IsNullOrWhiteSpace(response))
  2263. {
  2264. // 预处理:过滤 AI 可能返回的 Markdown 标记
  2265. string cleanJson = response.Trim();
  2266. if (cleanJson.StartsWith("```json"))
  2267. cleanJson = cleanJson.Substring(7, cleanJson.Length - 10).Trim();
  2268. else if (cleanJson.StartsWith("```"))
  2269. cleanJson = cleanJson.Substring(3, cleanJson.Length - 6).Trim();
  2270. try
  2271. {
  2272. // 解析并注入 Source 标识
  2273. hunyuanAIInvDatas = JsonConvert.DeserializeObject<List<InvitationAIInfo>>(cleanJson);
  2274. if (hunyuanAIInvDatas != null)
  2275. {
  2276. hunyuanAIInvDatas = hunyuanAIInvDatas.Select(x =>
  2277. {
  2278. x.Guid = Guid.NewGuid().ToString("N");
  2279. x.Source = 1;
  2280. //x.Region = entryInfo.TargetCountry;
  2281. x.Operator = operatorName;
  2282. x.OperatedAt = DateTime.Now;
  2283. return x;
  2284. }).ToList();
  2285. }
  2286. }
  2287. catch (JsonException ex)
  2288. {
  2289. // 记录日志并考虑 fallback 策略
  2290. _logger.LogError(ex, "Hunyuan AI 响应解析失败。原始数据:{Response}", response);
  2291. }
  2292. }
  2293. }
  2294. #endregion
  2295. #region 数据库操作
  2296. // 数据整合 (高效合并)
  2297. var finalResult = localInvDatas.Concat(hunyuanAIInvDatas).ToList();
  2298. string invName = $"{entryInfo.OriginUnit}拜访{entryInfo.TargetCountry}";
  2299. invAiInfo.AiCrawledDetails = finalResult;
  2300. var update = await _sqlSugar.Updateable(invAiInfo).ExecuteCommandAsync();
  2301. if (update < 1)
  2302. {
  2303. return Ok(JsonView(false, $"数据更新失败!"));
  2304. }
  2305. #endregion
  2306. return Ok(JsonView(true, $"查询成功!", new
  2307. {
  2308. invAiInfo.Id,
  2309. invAiInfo.InvName,
  2310. invAiInfo.GroupId,
  2311. AiCrawledDetails = invAiInfo.AiCrawledDetails.OrderByDescending(x => x.OperatedAt).ToList(),
  2312. Entry = invAiInfo.EntryInfo
  2313. }));
  2314. }
  2315. /// <summary>
  2316. /// 商邀资料AI 混元AI查询资料(SSE流式推送)
  2317. /// </summary>
  2318. [HttpPost]
  2319. public async Task InvitationAISearchStreamProgress([FromBody] InvitationAISearchDto dto)
  2320. {
  2321. // 强制关闭响应缓冲
  2322. var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();
  2323. if (syncIOFeature != null) syncIOFeature.AllowSynchronousIO = true;
  2324. var response = HttpContext.Response;
  2325. // --- SSE 核心协议头配置 ---
  2326. response.Headers.Add("Content-Type", "text/event-stream");
  2327. response.Headers.Add("Cache-Control", "no-cache");
  2328. response.Headers.Add("Connection", "keep-alive");
  2329. response.Headers.Add("X-Accel-Buffering", "no");
  2330. // 定义流式推送匿名函数
  2331. async Task SendStep(int progress, string message, object data = null)
  2332. {
  2333. var settings = new JsonSerializerSettings
  2334. {
  2335. ContractResolver = new CamelCasePropertyNamesContractResolver() // 强制小驼峰转换
  2336. };
  2337. var payload = JsonConvert.SerializeObject(new { progress, message, data }, settings);
  2338. var bytes = Encoding.UTF8.GetBytes($"data: {payload}\n\n");
  2339. await response.Body.WriteAsync(bytes, 0, bytes.Length);
  2340. await response.Body.FlushAsync(); // 立即清空缓冲区发送
  2341. }
  2342. try
  2343. {
  2344. await SendStep(5, "正在加载配置参数...");
  2345. #region 1. 参数与权限验证
  2346. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.Id == dto.Id).FirstAsync();
  2347. if (invAiInfo?.EntryInfo == null)
  2348. {
  2349. await SendStep(-1, "未找到有效的关键字配置信息。");
  2350. return;
  2351. }
  2352. var entryInfo = invAiInfo.EntryInfo;
  2353. var operatorName = await _sqlSugar.Queryable<Sys_Users>()
  2354. .Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId)
  2355. .Select(x => x.CnName).FirstAsync() ?? "-";
  2356. #endregion
  2357. await SendStep(20, "正在翻阅本地典籍,执行高性能并行解密...");
  2358. #region 2. 本地数据并行解密 (Performance Boost)
  2359. var rawLocalDatas = await _sqlSugar.Queryable<Res_InvitationOfficialActivityData>()
  2360. .Where(x => x.IsDel == 0)
  2361. .ToListAsync();
  2362. // 使用 PLINQ 并行解密,极大提升解密密集型任务速度
  2363. var allDecrypted = rawLocalDatas.AsParallel().Select(item => new InvitationAIInfo
  2364. {
  2365. Guid = Guid.NewGuid().ToString("N"),
  2366. Source = 0,
  2367. Region = AesEncryptionHelper.Decrypt(item.Country),
  2368. NameCn = AesEncryptionHelper.Decrypt(item.UnitName),
  2369. Address = AesEncryptionHelper.Decrypt(item.Address),
  2370. Scope = AesEncryptionHelper.Decrypt(item.Field),
  2371. Contact = AesEncryptionHelper.Decrypt(item.Contact),
  2372. Phone = AesEncryptionHelper.Decrypt(item.Tel),
  2373. Email = AesEncryptionHelper.Decrypt(item.Email),
  2374. OperatedAt = DateTime.Now,
  2375. Operator = operatorName,
  2376. }).ToList();
  2377. // 筛选目标国家并计算 AI 缺口
  2378. var localInvDatas = new List<InvitationAIInfo>();
  2379. var aiTasks = new List<CountryAIPormptInfo>();
  2380. int targetPerCountry = entryInfo.NeedCount;
  2381. foreach (var countryName in entryInfo.TargetCountry)
  2382. {
  2383. var countryMatched = allDecrypted.Where(x => x.Region == countryName).Take(targetPerCountry).ToList();
  2384. localInvDatas.AddRange(countryMatched);
  2385. int gap = targetPerCountry - countryMatched.Count;
  2386. if (gap > 0) aiTasks.Add(new() { Country = countryName, Count = gap });
  2387. }
  2388. #endregion
  2389. #region 3. 混元 AI 远程炼金
  2390. var hunyuanAIInvDatas = new List<InvitationAIInfo>();
  2391. if (aiTasks.Any())
  2392. {
  2393. await SendStep(60, $"正在召唤混元 AI:检索 {aiTasks.Count} 个国家的邀请信息...");
  2394. string question = BuildHunyuanPrompt(aiTasks, entryInfo); // 抽离 Prompt 构造
  2395. string aiRawResponse = string.Empty;
  2396. try
  2397. {
  2398. aiRawResponse = await _hunyuanService.ChatCompletionsHunyuan_t1_latestAsync(question);
  2399. // 清理 Markdown 代码块包裹
  2400. string cleanJson = aiRawResponse.Trim();
  2401. if (cleanJson.StartsWith("```json")) cleanJson = cleanJson[7..^3].Trim();
  2402. else if (cleanJson.StartsWith("```")) cleanJson = cleanJson[3..^3].Trim();
  2403. var aiParsed = JsonConvert.DeserializeObject<List<InvitationAIInfo>>(cleanJson);
  2404. if (aiParsed != null)
  2405. {
  2406. hunyuanAIInvDatas = aiParsed.Select(x => {
  2407. x.Guid = Guid.NewGuid().ToString("N");
  2408. x.Source = 1; // AI 来源
  2409. x.Operator = operatorName;
  2410. x.OperatedAt = DateTime.Now;
  2411. return x;
  2412. }).ToList();
  2413. }
  2414. }
  2415. catch (Exception ex)
  2416. {
  2417. _logger.LogError(ex, "AI 接口调用或解析失败");
  2418. await SendStep(60, "警告:AI 检索部分失败,将仅展示本地数据。");
  2419. }
  2420. }
  2421. #endregion
  2422. await SendStep(90, "执行数据合并与持久化...");
  2423. #region 4. 数据合并与入库
  2424. var finalResult = localInvDatas.Concat(hunyuanAIInvDatas).ToList();
  2425. invAiInfo.AiCrawledDetails = finalResult;
  2426. var updateSuccess = await _sqlSugar.Updateable(invAiInfo).ExecuteCommandAsync() > 0;
  2427. if (!updateSuccess)
  2428. {
  2429. await SendStep(-1, "数据库更新异常。");
  2430. return;
  2431. }
  2432. #endregion
  2433. // 5. 最终推送:带上全量结果
  2434. await SendStep(100, "操作成功!资料已全部就绪。", new
  2435. {
  2436. invAiInfo.Id,
  2437. invAiInfo.InvName,
  2438. AiCrawledDetails = finalResult.OrderByDescending(x => x.OperatedAt).ToList(),
  2439. Entry = invAiInfo.EntryInfo
  2440. });
  2441. }
  2442. catch (Exception ex)
  2443. {
  2444. _logger.LogError(ex, "SSE 发生不可预知异常");
  2445. await SendStep(-1, $"炼金炸炉:{ex.Message}");
  2446. }
  2447. finally
  2448. {
  2449. // 确保最后一次冲刷缓冲区
  2450. await HttpContext.Response.Body.FlushAsync();
  2451. // 此时方法结束,ASP.NET Core 会自动处理连接关闭
  2452. _logger.LogInformation("SSE 炼金通道已安全关闭");
  2453. // :直接完成响应流
  2454. await response.CompleteAsync();
  2455. }
  2456. return;
  2457. }
  2458. private string BuildHunyuanPrompt(List<CountryAIPormptInfo> tasks, EntryInfo entryInfo)
  2459. {
  2460. // 保持你原有的高质量 Prompt 结构
  2461. return @$"# [SYSTEM_CONTEXT]
  2462. - Role: Senior Business Consultant (Global Supply Chain & Cross-border Trade Expert)
  2463. - Framework: S.P.A.R. (Situation-Problem-Action-Result)
  2464. - Target Architecture: .NET 6 DTO Compatible Interface
  2465. # [INPUT_CONFIG]
  2466. - Tasks: {{{JsonConvert.SerializeObject(tasks)}}}
  2467. - OriginUnit: {{{entryInfo.OriginUnit}}}
  2468. - Objective: {{{entryInfo.Objective}}}
  2469. - OtherConstraints: {{{entryInfo.OtherConstraints}}}
  2470. # [ROLE_DEFINITION]
  2471. 你是一位精通全球跨境经贸、海外园区政策及 Tasks 中的国家本地准入法规的【顶级商务咨询顾问】。你擅长通过“产业链对等原则(Chain-Parity Principle)”为跨国企业精准匹配具备落地价值的合作伙伴。
  2472. # [BUSINESS_LOGIC_CoT]
  2473. 在生成结果前,请严格执行以下思维链拆解:
  2474. 1. **ScopePartitioning**: 遍历 Tasks 中的每个国家。
  2475. 1. **EntityProfiling**: 识别 {{OriginUnit}} 的核心生态位(如:Supply/Demand/Capital/Logistics)。
  2476. 2. **ParityMatching**: 针对每个国家,检索境内业务闭环对等机构。(例如:若 Origin 为分销,则 Target 为源头工厂/种植园)。
  2477. 3. **RegulatoryCheck**: 验证目标机构的合规性(如:GACC 备案、SPS 协议、或当地政府特许经营权)。
  2478. 4. **DataSynthesis**: 必须严格根据每个国家对应的 Count 生成数据条数。针对无法直接获取的动态(如 PostUrl),优先检索其官网 News 频道或 LinkedIn 企业号。
  2479. # [CONSTRAINTS_&_STANDARDS]
  2480. - **NamingConvention**: 所有 JSON Key 必须严格遵循 **PascalCase**(例如:`UnitNameCn` 而非 `unit_name_cn`)。
  2481. - **DataIntegrity**:
  2482. - 总条数必须等于 Tasks 中所有 Count 的总和。
  2483. - 优先级:Core (核心机构) > Backup (关联替代机构)。
  2484. - **ValidationRules**:
  2485. - `Phone`: 必须包含 Tasks 中的国家国际区号(如 +856, +66 等)。
  2486. - `IntgAdvice`: 必须包含“对等性分析”,解释该机构如何与 {{OriginUnit}} 形成业务闭环(50-100字)。
  2487. - `Status`: 若字段确实无法获取,统一填充 'N/A',禁止编造。
  2488. - **Safety**: 确保推荐机构不涉及敏感黑名单或已破产企业。
  2489. # [INFORMATION_SCHEMA]
  2490. 请将结果填充至以下结构的 JSON 数组中:
  2491. - Region:国家(必须与 Tasks 中的 Country 完全匹配)
  2492. - NameCn: 单位名称(中文)
  2493. - NameEn: 单位名称(英文)
  2494. - Address: 详细地理位置(含省市区街道)
  2495. - Scope: 经营范围(需强调其出口配额、生产能力或行业地位)
  2496. - Contact: 联系人姓名及职务
  2497. - Phone: 拨打全号(含区号)
  2498. - Email: 商务联络邮箱
  2499. - SiteUrl: 官方网站或权威社媒主页
  2500. - PostUrl: 近一年内的商务动态/新闻链接
  2501. - RecLevel: 推荐等级(枚举值:Core, Backup)
  2502. - IntgAdvice: 对接深度建议(基于产业链交合、互补逻辑)
  2503. # [OUTPUT_PROTOCOL]
  2504. - 仅输出一个标准的 JSON Array 字符串。
  2505. - 严禁任何 Markdown 说明文字、代码块之外的解释或开场白。
  2506. - 确保 JSON 语法在 .NET `JsonSerializer.Deserialize` 下可直接解析。
  2507. # [EXECUTION]
  2508. 根据以上配置,开始生成。"; ;
  2509. }
  2510. /// <summary>
  2511. /// 商邀资料AI 设置词条
  2512. /// </summary>
  2513. /// <returns></returns>
  2514. [HttpPost]
  2515. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  2516. public async Task<IActionResult> InvitationAISetPrompt(InvitationAISetPromptDto dto)
  2517. {
  2518. // 基础校验
  2519. if (string.IsNullOrWhiteSpace(dto.OriginUnit) || dto.TargetCountry == null || dto.TargetCountry.Count == 0)
  2520. return Ok(JsonView(false, "请传入有效的单位名称和国家!"));
  2521. var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>()
  2522. .Where(x => x.IsDel == 0 && x.Id == dto.GroupId)
  2523. .Select(x => new { x.TeamName, x.VisitPurpose })
  2524. .FirstAsync();
  2525. string invName = $"{dto.OriginUnit}拜访{string.Join("、",dto.TargetCountry)}";
  2526. #region 数据库操作
  2527. // 数据库信息获取方式
  2528. // 1.通过团组 GroupId 关联查询
  2529. var dataInfo = await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.IsDel == 0 && x.GroupId == dto.GroupId).FirstAsync();
  2530. // 2.通过InvName 关联查询(考虑到可能存在同名情况,优先使用 GroupId 关联查询,确保数据准确性)
  2531. dataInfo ??= await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.IsDel == 0 && x.InvName == invName).FirstAsync();
  2532. #region 词条信息
  2533. string operatorName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
  2534. var entryInfo = new EntryInfo()
  2535. {
  2536. OriginUnit = dto.OriginUnit,
  2537. TargetCountry = dto.TargetCountry,
  2538. Objective = groupInfo?.VisitPurpose ?? "商务考察与合作对接",
  2539. OtherConstraints = dto.OtherConstraints,
  2540. Operator = operatorName,
  2541. OperatedAt = DateTime.Now
  2542. };
  2543. #endregion
  2544. // 3.如果以上两种方式都没有查询到数据,则说明是新数据,需要添加到数据库
  2545. if (dataInfo == null)
  2546. {
  2547. // 3.1 新数据,需要添加到数据库
  2548. dataInfo = new Res_InvitationAI()
  2549. {
  2550. InvName = groupInfo?.TeamName ?? invName, //默认团组名称
  2551. GroupId = dto.GroupId,
  2552. EntryInfo = entryInfo,
  2553. CreateUserId = dto.CurrUserId
  2554. };
  2555. var insert = await _sqlSugar.Insertable(dataInfo).ExecuteReturnIdentityAsync();
  2556. if (insert < 1)
  2557. {
  2558. return Ok(JsonView(false, $"词条信息新增失败!"));
  2559. }
  2560. dataInfo.Id = insert;
  2561. }
  2562. else
  2563. {
  2564. // 3.2 数据存在 则更新数据(覆盖原有的AI爬取详情,保留原有的其他字段不变)
  2565. dataInfo.EntryInfo = entryInfo;
  2566. var update = await _sqlSugar.Updateable(dataInfo).ExecuteCommandAsync();
  2567. if (update < 1)
  2568. {
  2569. return Ok(JsonView(false, $"词条信息更新失败!"));
  2570. }
  2571. }
  2572. #endregion
  2573. return Ok(JsonView(true, $"设置成功!", new
  2574. {
  2575. dataInfo.Id,
  2576. dataInfo.InvName,
  2577. dataInfo.GroupId,
  2578. Entry = dataInfo.EntryInfo,
  2579. }));
  2580. }
  2581. /// <summary>
  2582. /// 商邀资料AI 设置复选框选中 批量
  2583. /// </summary>
  2584. /// <param name="dto"></param>
  2585. /// <returns></returns>
  2586. /// <summary>
  2587. /// 商邀资料AI 设置复选框选中 批量 (支持传入空数组进行重置)
  2588. /// </summary>
  2589. [HttpPost]
  2590. public async Task<IActionResult> InvitationAISetChecked([FromBody] InvitationAISetCheckedDto dto)
  2591. {
  2592. // 1. 基础参数校验 (注意:这里移除了对 Guids.Any() 的强校验,允许空集合)
  2593. if (dto.Id < 1 || dto.CurrUserId < 1 || dto.Guids == null)
  2594. return Ok(JsonView(false, "请求参数不完整"));
  2595. // 2. 获取主记录
  2596. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>()
  2597. .FirstAsync(x => x.IsDel == 0 && x.Id == dto.Id);
  2598. if (invAiInfo?.AiCrawledDetails == null || !invAiInfo.AiCrawledDetails.Any())
  2599. return Ok(JsonView(false, "数据不存在或集合为空"));
  2600. // 3. 准备更新所需数据
  2601. var guidSet = dto.Guids.ToHashSet();
  2602. var now = DateTime.Now;
  2603. // 获取操作人姓名
  2604. string operatorName = await _sqlSugar.Queryable<Sys_Users>()
  2605. .Where(x => x.Id == dto.CurrUserId)
  2606. .Select(x => x.CnName)
  2607. .FirstAsync() ?? "-";
  2608. // 4. 单次遍历完成 重置 + 更新
  2609. // 如果 guidSet 为空,循环会将所有项的 IsChecked 置为 false
  2610. foreach (var item in invAiInfo.AiCrawledDetails)
  2611. {
  2612. if (guidSet.Contains(item.Guid))
  2613. {
  2614. item.IsChecked = true;
  2615. }
  2616. else
  2617. {
  2618. item.IsChecked = false;
  2619. }
  2620. item.OperatedAt = now;
  2621. item.Operator = operatorName;
  2622. }
  2623. // 5. 排序逻辑
  2624. // 即使是全量取消选中,也可以按最后操作时间排序,让最近变动的项在前
  2625. invAiInfo.AiCrawledDetails = invAiInfo.AiCrawledDetails
  2626. .OrderByDescending(x => x.OperatedAt)
  2627. .ToList();
  2628. // 6. 提交数据库
  2629. // 注意:SqlSugar 的 UpdateColumns 会序列化整个对象列表并覆盖数据库字段
  2630. await _sqlSugar.Updateable(invAiInfo)
  2631. .UpdateColumns(x => x.AiCrawledDetails)
  2632. .ExecuteCommandAsync();
  2633. return Ok(JsonView(true, guidSet.Any() ? "设置成功" : "已全部取消选中"));
  2634. }
  2635. /// <summary>
  2636. /// 商邀资料AI 保存
  2637. /// </summary>
  2638. /// <returns></returns>
  2639. [HttpPost]
  2640. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  2641. public async Task<IActionResult> InvitationAISave(InvitationAISaveDto dto)
  2642. {
  2643. if (dto.Id < 1) return Ok(JsonView(false, "请选择保存的团组"));
  2644. if (dto.CurrUserId < 1) return Ok(JsonView(false, "请传入用户Id"));
  2645. if (dto.AiCrawledDetail == null) return Ok(JsonView(false, "请选择保存的邀请方详情"));
  2646. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>()
  2647. .Where(x => x.Id == dto.Id)
  2648. .FirstAsync();
  2649. if (invAiInfo == null) return Ok(JsonView(false, "数据信息为空"));
  2650. var dataList = invAiInfo?.AiCrawledDetails;
  2651. if (dataList == null) return Ok(JsonView(false, "邀请方数据信息为空"));
  2652. var datas = dataList.Where(x => x.Guid != dto.AiCrawledDetail.Guid).ToList();
  2653. var editInfo = dto.AiCrawledDetail;
  2654. var opUserName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
  2655. editInfo.Operator = opUserName;
  2656. editInfo.OperatedAt = DateTime.Now;
  2657. datas.Add(editInfo);
  2658. invAiInfo.AiCrawledDetails = datas.OrderByDescending(x => x.OperatedAt).ToList();
  2659. var editUpd = await _sqlSugar.Updateable(invAiInfo).UpdateColumns(x => x.AiCrawledDetails).ExecuteCommandAsync();
  2660. if (editUpd < 1)
  2661. {
  2662. return Ok(JsonView(true, "保存失败"));
  2663. }
  2664. return Ok(JsonView(true, "保存成功"));
  2665. }
  2666. /// <summary>
  2667. /// 商邀资料AI 单条删除
  2668. /// </summary>
  2669. /// <returns></returns>
  2670. [HttpPost]
  2671. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  2672. public async Task<IActionResult> InvitationAISingleDel(InvitationAISingleDelDto dto)
  2673. {
  2674. int id = dto.Id;
  2675. string guid = dto.Guid;
  2676. // 基础校验
  2677. if (id < 1 || string.IsNullOrWhiteSpace(guid))
  2678. return Ok(JsonView(false, "请传入有效的Id和Guid!"));
  2679. var dataInfo = await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.IsDel == 0 && x.Id == id).FirstAsync();
  2680. if (dataInfo == null)
  2681. return Ok(JsonView(false, "当前数据信息不存在!"));
  2682. var newDataInfos = dataInfo.AiCrawledDetails.Where(x => x.Guid != guid).ToList();
  2683. dataInfo.AiCrawledDetails = newDataInfos.OrderByDescending(x => x.OperatedAt).ToList();
  2684. var update = await _sqlSugar.Updateable(dataInfo).ExecuteCommandAsync();
  2685. if (update < 1)
  2686. {
  2687. return Ok(JsonView(false, $"删除失败!"));
  2688. }
  2689. return Ok(JsonView(true, $"删除成功!", new
  2690. {
  2691. dataInfo.Id,
  2692. dataInfo.InvName,
  2693. dataInfo.GroupId,
  2694. dataInfo.AiCrawledDetails
  2695. }));
  2696. }
  2697. /// <summary>
  2698. /// 商邀资料AI AI查询出的数据添加值商邀资料库
  2699. /// </summary>
  2700. /// <returns></returns>
  2701. [HttpPost]
  2702. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  2703. public async Task<IActionResult> InvitationAIInsertResource([FromBody] InvitationAIInsertResourceDto dto)
  2704. {
  2705. // 基础校验
  2706. if (dto.Id < 1 || dto.CurrUserId < 1 || dto.Guids == null || !dto.Guids.Any())
  2707. return Ok(JsonView(false, "参数不完整,请选择有效的单位数据"));
  2708. // 获取主记录
  2709. var dataInfo = await _sqlSugar.Queryable<Res_InvitationAI>()
  2710. .FirstAsync(x => x.IsDel == 0 && x.Id == dto.Id);
  2711. if (dataInfo?.AiCrawledDetails == null)
  2712. return Ok(JsonView(false, "当前数据信息不存在!"));
  2713. // 筛选出待转正的 AI 数据 (使用 HashSet 优化匹配)
  2714. var guidSet = dto.Guids.ToHashSet();
  2715. var targetAiDetails = dataInfo.AiCrawledDetails
  2716. .Where(x => x.Source == 1 && guidSet.Contains(x.Guid))
  2717. .ToList();
  2718. if (!targetAiDetails.Any())
  2719. return Ok(JsonView(false, "未找到符合条件的 AI 获取信息,无法重复添加或来源错误!"));
  2720. // 准备入库数据(批量构建)
  2721. var now = DateTime.Now;
  2722. var opUserName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
  2723. var rawLocalDatas = targetAiDetails.Select(item => {
  2724. // 修改内存中的状态为本地数据
  2725. item.Source = 0;
  2726. item.OperatedAt = now;
  2727. item.Operator = opUserName;
  2728. return new Res_InvitationOfficialActivityData()
  2729. {
  2730. // 批量加密操作
  2731. Country = AesEncryptionHelper.Encrypt(item.Region),
  2732. UnitName = AesEncryptionHelper.Encrypt(item.NameCn),
  2733. Address = AesEncryptionHelper.Encrypt(item.Address),
  2734. Field = AesEncryptionHelper.Encrypt(item.Scope),
  2735. Contact = AesEncryptionHelper.Encrypt(item.Contact),
  2736. Tel = AesEncryptionHelper.Encrypt(item.Phone),
  2737. Email = AesEncryptionHelper.Encrypt(item.Email),
  2738. UnitWeb = AesEncryptionHelper.Encrypt(item.SiteUrl),
  2739. LastUpdateUserId = dto.CurrUserId,
  2740. LastUpdateTime = now,
  2741. CreateUserId = dto.CurrUserId,
  2742. CreateTime = now
  2743. };
  2744. }).ToList();
  2745. // 开启事务执行双表更新
  2746. var result = await _sqlSugar.UseTranAsync(async () =>
  2747. {
  2748. // 插入本地资料库
  2749. await _sqlSugar.Insertable(rawLocalDatas).ExecuteCommandAsync();
  2750. // 更新 AI 主表的状态(全量覆盖 JSON 列)
  2751. await _sqlSugar.Updateable(dataInfo)
  2752. .UpdateColumns(x => x.AiCrawledDetails)
  2753. .ExecuteCommandAsync();
  2754. });
  2755. return Ok(result.IsSuccess
  2756. ? JsonView(true, "成功添加至资料库并更新来源状态")
  2757. : JsonView(false, $"操作失败:{result.ErrorMessage}"));
  2758. }
  2759. /// <summary>
  2760. /// 商邀资料AI 混元AI续写
  2761. /// </summary>
  2762. /// <returns></returns>
  2763. [HttpPost]
  2764. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  2765. public async Task<IActionResult> InvitationAICompleteText(InvitationAICompleteTextDto dto)
  2766. {
  2767. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.Id == dto.Id).FirstAsync();
  2768. if (invAiInfo == null || invAiInfo?.EntryInfo == null)
  2769. {
  2770. return Ok(JsonView(false, "请先设置关键字信息!"));
  2771. }
  2772. var entryInfo = invAiInfo.EntryInfo;
  2773. // 记录:国家 -> 需要补齐的数量
  2774. var aiTasks = new List<CountryAIPormptInfo>();
  2775. // 单个国家数据总条数
  2776. int targetPerCountry = invAiInfo.EntryInfo?.NeedCount ?? 10;
  2777. foreach (var countryName in entryInfo.TargetCountry)
  2778. {
  2779. var countryDataCount = invAiInfo.AiCrawledDetails.Count(x => x.Region == countryName);
  2780. int aiNeedCount = targetPerCountry - countryDataCount;
  2781. if (aiNeedCount > 0)
  2782. {
  2783. aiTasks.Add(new() { Country = countryName, Count = aiNeedCount });
  2784. }
  2785. }
  2786. // 已搜索出的数据(AI 数据源)
  2787. var hunyuanAIDatas = invAiInfo.AiCrawledDetails.Where(x => x.Source == 1).ToList() ?? new List<InvitationAIInfo>();
  2788. // 当前企业领域
  2789. string industryFocus = string.Empty;
  2790. // 词条
  2791. string question = string.Empty;
  2792. string operatorName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
  2793. #region 混元AI 获取商邀资料
  2794. var hunyuanAIInvDatas = new List<InvitationAIInfo>();
  2795. // 已存在数据名称整理
  2796. var existingNames = new HashSet<string>(hunyuanAIDatas.Select(x => x.NameCn));
  2797. entryInfo.OtherConstraints = $"请基于以下已存在的名称列表进行推荐,避免重复:{string.Join(", ", existingNames)}。{entryInfo.OtherConstraints}";
  2798. if (aiTasks != null && aiTasks.Count > 0)
  2799. {
  2800. question = @$"# [SYSTEM_CONTEXT]
  2801. - Role: Senior Business Consultant (Global Supply Chain & Cross-border Trade Expert)
  2802. - Framework: S.P.A.R. (Situation-Problem-Action-Result)
  2803. - Target Architecture: .NET 6 DTO Compatible Interface
  2804. # [INPUT_CONFIG]
  2805. - Tasks: {{{JsonConvert.SerializeObject(aiTasks)}}}
  2806. - OriginUnit: {{{entryInfo.OriginUnit}}}
  2807. - Objective: {{{entryInfo.Objective}}}
  2808. - OtherConstraints: {{{entryInfo.OtherConstraints}}}
  2809. # [ROLE_DEFINITION]
  2810. 你是一位精通全球跨境经贸、海外园区政策及 Tasks 中的国家本地准入法规的【顶级商务咨询顾问】。你擅长通过“产业链对等原则(Chain-Parity Principle)”为跨国企业精准匹配具备落地价值的合作伙伴。
  2811. # [BUSINESS_LOGIC_CoT]
  2812. 在生成结果前,请严格执行以下思维链拆解:
  2813. 1. **ScopePartitioning**: 遍历 Tasks 中的每个国家。
  2814. 1. **EntityProfiling**: 识别 {{OriginUnit}} 的核心生态位(如:Supply/Demand/Capital/Logistics)。
  2815. 2. **ParityMatching**: 针对每个国家,检索境内业务闭环对等机构。(例如:若 Origin 为分销,则 Target 为源头工厂/种植园)。
  2816. 3. **RegulatoryCheck**: 验证目标机构的合规性(如:GACC 备案、SPS 协议、或当地政府特许经营权)。
  2817. 4. **DataSynthesis**: 必须严格根据每个国家对应的 Count 生成数据条数。针对无法直接获取的动态(如 PostUrl),优先检索其官网 News 频道或 LinkedIn 企业号。
  2818. # [CONSTRAINTS_&_STANDARDS]
  2819. - **NamingConvention**: 所有 JSON Key 必须严格遵循 **PascalCase**(例如:`UnitNameCn` 而非 `unit_name_cn`)。
  2820. - **DataIntegrity**:
  2821. - 总条数必须等于 Tasks 中所有 Count 的总和。
  2822. - 优先级:Core (核心机构) > Backup (关联替代机构)。
  2823. - **ValidationRules**:
  2824. - `Phone`: 必须包含 Tasks 中的国家国际区号(如 +856, +66 等)。
  2825. - `IntgAdvice`: 必须包含“对等性分析”,解释该机构如何与 {{OriginUnit}} 形成业务闭环(50-100字)。
  2826. - `Status`: 若字段确实无法获取,统一填充 'N/A',禁止编造。
  2827. - **Safety**: 确保推荐机构不涉及敏感黑名单或已破产企业。
  2828. # [INFORMATION_SCHEMA]
  2829. 请将结果填充至以下结构的 JSON 数组中:
  2830. - Region:国家(必须与 Tasks 中的 Country 完全匹配)
  2831. - NameCn: 单位名称(中文)
  2832. - NameEn: 单位名称(英文)
  2833. - Address: 详细地理位置(含省市区街道)
  2834. - Scope: 经营范围(需强调其出口配额、生产能力或行业地位)
  2835. - Contact: 联系人姓名及职务
  2836. - Phone: 拨打全号(含区号)
  2837. - Email: 商务联络邮箱
  2838. - SiteUrl: 官方网站或权威社媒主页
  2839. - PostUrl: 近一年内的商务动态/新闻链接
  2840. - RecLevel: 推荐等级(枚举值:Core, Backup)
  2841. - IntgAdvice: 对接深度建议(基于产业链交合、互补逻辑)
  2842. # [OUTPUT_PROTOCOL]
  2843. - 仅输出一个标准的 JSON Array 字符串。
  2844. - 严禁任何 Markdown 说明文字、代码块之外的解释或开场白。
  2845. - 确保 JSON 语法在 .NET `JsonSerializer.Deserialize` 下可直接解析。
  2846. # [EXECUTION]
  2847. 根据以上配置,开始生成。";
  2848. string response = string.Empty;
  2849. try
  2850. {
  2851. response = await _hunyuanService.ChatCompletionsHunyuan_t1_latestAsync(question);
  2852. }
  2853. catch (HttpRequestException ex)
  2854. {
  2855. _logger.LogError(ex, "网络连接失败,无法调用混元API");
  2856. return Ok(JsonView(false, $"网络连接异常,请检查网络后重试!Ex:{ex.Message}"));
  2857. }
  2858. catch (TaskCanceledException ex)
  2859. {
  2860. _logger.LogError(ex, "请求超时");
  2861. return Ok(JsonView(false, $"AI 响应超时,请稍后再试!Ex:{ex.Message}"));
  2862. }
  2863. catch (TencentCloudSDKException ex)
  2864. {
  2865. // 记录完整日志
  2866. _logger.LogError(ex, "腾讯云API调用失败 | 错误码: {ErrorCode} | 请求ID: {RequestId}", ex.ErrorCode, ex.RequestId);
  2867. // 根据错误码做差异化处理
  2868. if (ex.ErrorCode != null && ex.ErrorCode == "AuthFailure.SignatureExpire")
  2869. {
  2870. return Ok(JsonView(false, $"系统时间异常,请同步时间后重试!Ex:{ex.Message}"));
  2871. }
  2872. else if (ex.ErrorCode != null && ex.ErrorCode.StartsWith("Unauthorized"))
  2873. {
  2874. return Ok(JsonView(false, $"当前账号无权限访问该服务!Ex:{ex.Message}"));
  2875. }
  2876. else
  2877. {
  2878. return Ok(JsonView(false, $"腾讯云服务调用失败,请稍后重试!Ex:{ex.Message}"));
  2879. }
  2880. }
  2881. catch (Exception ex)
  2882. {
  2883. _logger.LogError(ex, "未知错误,调用混元API失败");
  2884. return Ok(JsonView(false, $"未知错误,调用混元API失败!Ex:{ex.Message}"));
  2885. }
  2886. if (!string.IsNullOrWhiteSpace(response))
  2887. {
  2888. // 预处理:过滤 AI 可能返回的 Markdown 标记
  2889. string cleanJson = response.Trim();
  2890. if (cleanJson.StartsWith("```json"))
  2891. cleanJson = cleanJson.Substring(7, cleanJson.Length - 10).Trim();
  2892. else if (cleanJson.StartsWith("```"))
  2893. cleanJson = cleanJson.Substring(3, cleanJson.Length - 6).Trim();
  2894. try
  2895. {
  2896. // 解析并注入 Source 标识
  2897. hunyuanAIInvDatas = JsonConvert.DeserializeObject<List<InvitationAIInfo>>(cleanJson);
  2898. if (hunyuanAIInvDatas != null)
  2899. {
  2900. hunyuanAIInvDatas = hunyuanAIInvDatas.Select(x =>
  2901. {
  2902. x.Guid = Guid.NewGuid().ToString("N");
  2903. x.Source = 1;
  2904. //x.Region = entryInfo.TargetCountry;
  2905. x.Operator = operatorName;
  2906. x.OperatedAt = DateTime.Now;
  2907. return x;
  2908. }).ToList();
  2909. }
  2910. }
  2911. catch (JsonException ex)
  2912. {
  2913. // 记录日志并考虑 fallback 策略
  2914. _logger.LogError(ex, "Hunyuan AI 响应解析失败。原始数据:{Response}", response);
  2915. }
  2916. }
  2917. #region 数据库操作
  2918. invAiInfo.AiCrawledDetails.AddRange(hunyuanAIInvDatas);
  2919. invAiInfo.AiCrawledDetails = invAiInfo.AiCrawledDetails.OrderByDescending(x => x.OperatedAt).ToList();
  2920. var update = await _sqlSugar.Updateable(invAiInfo).ExecuteCommandAsync();
  2921. if (update < 1)
  2922. {
  2923. return Ok(JsonView(false, $"AI续写,数据更新失败!"));
  2924. }
  2925. return Ok(JsonView(true, $"AI续写成功!操作数据{hunyuanAIInvDatas.Count}条"));
  2926. #endregion
  2927. }
  2928. #endregion
  2929. return Ok(JsonView(false, $"AI续写失败!"));
  2930. }
  2931. /// <summary>
  2932. /// 商邀资料AI 混元AI续写(SSE流式推送)
  2933. /// </summary>
  2934. /// <param name="dto"></param>
  2935. /// <returns></returns>
  2936. [HttpPost]
  2937. public async Task InvitationAICompleteTextStream([FromBody] InvitationAICompleteTextDto dto)
  2938. {
  2939. var response = HttpContext.Response;
  2940. response.Headers.Add("Content-Type", "text/event-stream");
  2941. response.Headers.Add("Cache-Control", "no-cache");
  2942. response.Headers.Add("Connection", "keep-alive");
  2943. response.Headers.Add("X-Accel-Buffering", "no"); // 禁用 Nginx 缓存
  2944. // 内部推送工具
  2945. async Task SendStep(int progress, string msg, object data = null)
  2946. {
  2947. var payload = JsonConvert.SerializeObject(new
  2948. {
  2949. progress,
  2950. message = msg,
  2951. data,
  2952. operatedAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
  2953. });
  2954. await response.WriteAsync($"data: {payload}\n\n");
  2955. await response.Body.FlushAsync();
  2956. }
  2957. try
  2958. {
  2959. // 初始化检查 (Progress: 5%)
  2960. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.Id == dto.Id).FirstAsync();
  2961. if (invAiInfo?.EntryInfo == null)
  2962. {
  2963. await SendStep(-1, "请先设置关键字信息!");
  2964. return;
  2965. }
  2966. await SendStep(10, "任务初始化完成,正在计算补齐缺口...");
  2967. // 任务拆解逻辑
  2968. var entryInfo = invAiInfo.EntryInfo;
  2969. var aiTasks = new List<CountryAIPormptInfo>();
  2970. int targetPerCountry = entryInfo.NeedCount;
  2971. foreach (var countryName in entryInfo.TargetCountry)
  2972. {
  2973. var countryDataCount = invAiInfo.AiCrawledDetails.Count(x => x.Region == countryName);
  2974. int aiNeedCount = targetPerCountry - countryDataCount;
  2975. if (aiNeedCount > 0) aiTasks.Add(new() { Country = countryName, Count = aiNeedCount });
  2976. }
  2977. if (!aiTasks.Any())
  2978. {
  2979. await SendStep(100, "数据已满额,无需续写", invAiInfo.AiCrawledDetails);
  2980. return;
  2981. }
  2982. // 准备 AI Prompt (Progress: 20%)
  2983. var existingNames = new HashSet<string>(invAiInfo.AiCrawledDetails.Where(x => x.Source == 1).Select(x => x.NameCn));
  2984. string promptOther = $"请基于以下已存在的名称列表进行推荐,避免重复:{string.Join(", ", existingNames)}。{entryInfo.OtherConstraints}";
  2985. entryInfo.OtherConstraints = promptOther; // 将去重提示注入 entryInfo,确保 Prompt 构建时包含该信息
  2986. // 构建 Question
  2987. string question = BuildHunyuanPrompt(aiTasks, entryInfo);
  2988. await SendStep(30, "AI 正在深度检索跨境商邀数据,请稍候...");
  2989. // 调用 AI (Progress: 30% - 80%)
  2990. // 注意:这里如果能换成流式接口(ChatCompletionsStream)会更好,
  2991. // 如果依然用非流式,这里会有一段较长的等待。
  2992. string aiRawResponse = await _hunyuanService.ChatCompletionsHunyuan_t1_latestAsync(question);
  2993. await SendStep(85, "数据已捕获,正在进行格式校验与去重...");
  2994. // 5. 解析与清洗数据
  2995. var hunyuanAIInvDatas = ProcessAIResponse(aiRawResponse);
  2996. string operatorName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
  2997. foreach (var x in hunyuanAIInvDatas)
  2998. {
  2999. x.Guid = Guid.NewGuid().ToString("N");
  3000. x.Source = 1;
  3001. x.Operator = operatorName;
  3002. x.OperatedAt = DateTime.Now;
  3003. }
  3004. // 6. 数据库操作 (Progress: 95%)
  3005. invAiInfo.AiCrawledDetails.AddRange(hunyuanAIInvDatas);
  3006. invAiInfo.AiCrawledDetails = invAiInfo.AiCrawledDetails.OrderByDescending(x => x.OperatedAt).ToList();
  3007. var update = await _sqlSugar.Updateable(invAiInfo).UpdateColumns(x => x.AiCrawledDetails).ExecuteCommandAsync();
  3008. if (update > 0)
  3009. {
  3010. await SendStep(100, $"AI 续写成功!新增 {hunyuanAIInvDatas.Count} 条数据", invAiInfo.AiCrawledDetails);
  3011. }
  3012. else
  3013. {
  3014. await SendStep(-1, "数据库更新失败");
  3015. }
  3016. }
  3017. catch (Exception ex)
  3018. {
  3019. _logger.LogError(ex, "SSE 续写异常");
  3020. await SendStep(-1, $"炼金炸炉:{ex.Message}");
  3021. }
  3022. finally
  3023. {
  3024. await response.Body.FlushAsync();
  3025. await response.CompleteAsync(); // 彻底关闭连接
  3026. }
  3027. }
  3028. private List<InvitationAIInfo> ProcessAIResponse(string response)
  3029. {
  3030. if (string.IsNullOrWhiteSpace(response)) return new List<InvitationAIInfo>();
  3031. string cleanJson = response.Trim();
  3032. if (cleanJson.Contains("```json"))
  3033. {
  3034. cleanJson = Regex.Match(cleanJson, @"```json([\s\S]*?)```").Groups[1].Value.Trim();
  3035. }
  3036. else if (cleanJson.Contains("```"))
  3037. {
  3038. cleanJson = Regex.Match(cleanJson, @"```([\s\S]*?)```").Groups[1].Value.Trim();
  3039. }
  3040. return JsonConvert.DeserializeObject<List<InvitationAIInfo>>(cleanJson) ?? new List<InvitationAIInfo>();
  3041. }
  3042. /// <summary>
  3043. /// 商邀资料AI 文件生成(基于混元AI已爬取数据进行格式化输出,供用户下载使用)
  3044. /// </summary>
  3045. /// <returns></returns>
  3046. [HttpGet("{id}")]
  3047. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3048. public async Task<IActionResult> InvitationAIFileGenerator(int id)
  3049. {
  3050. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>()
  3051. .Where(x => x.Id == id)
  3052. .FirstAsync();
  3053. var dataList = invAiInfo?.AiCrawledDetails;
  3054. if (dataList == null)
  3055. return Ok(JsonView(false, "数据为空"));
  3056. Document doc = new Document();
  3057. DocumentBuilder builder = new DocumentBuilder(doc);
  3058. // A4页面设置
  3059. double usableWidth = 495;
  3060. foreach (Section sec in doc.Sections)
  3061. {
  3062. sec.PageSetup.PaperSize = Aspose.Words.PaperSize.A4;
  3063. sec.PageSetup.LeftMargin = 50;
  3064. sec.PageSetup.RightMargin = 50;
  3065. sec.PageSetup.TopMargin = 50;
  3066. sec.PageSetup.BottomMargin = 50;
  3067. }
  3068. // 卡片背景
  3069. Color cardBg = Color.FromArgb(252, 252, 252);
  3070. string fontName = "微软雅黑";
  3071. int count = 1;
  3072. foreach (var item in dataList)
  3073. {
  3074. // 标题
  3075. builder.ParagraphFormat.ClearFormatting();
  3076. builder.Font.ClearFormatting();
  3077. builder.Font.Name = fontName;
  3078. builder.Font.Size = 16;
  3079. builder.Font.Bold = true;
  3080. builder.Font.Color = Color.Black;
  3081. builder.Write($"{count++}. {item.NameCn}");
  3082. builder.InsertParagraph();
  3083. // 英文名
  3084. builder.Font.Size = 10;
  3085. builder.Font.Bold = false;
  3086. builder.Font.Color = Color.FromArgb(120, 120, 120);
  3087. builder.Write(item.NameEn ?? "");
  3088. builder.InsertParagraph();
  3089. builder.InsertParagraph();
  3090. // ====== 卡片表格 ======
  3091. Aspose.Words.Tables.Table table = builder.StartTable();
  3092. builder.CellFormat.Shading.BackgroundPatternColor = cardBg;
  3093. builder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
  3094. builder.CellFormat.WrapText = true;
  3095. builder.CellFormat.LeftPadding = 12;
  3096. builder.CellFormat.RightPadding = 12;
  3097. builder.CellFormat.TopPadding = 8;
  3098. builder.CellFormat.BottomPadding = 8;
  3099. double labelW = 120;
  3100. AddSingleRow(builder, fontName, labelW, usableWidth - labelW, "详细地址", item.Address);
  3101. AddSingleRow(builder, fontName, labelW, usableWidth - labelW, "联系人", item.Contact);
  3102. AddSingleRow(builder, fontName, labelW, usableWidth - labelW, "联系电话", item.Phone);
  3103. AddSingleRow(builder, fontName, labelW, usableWidth - labelW, "电子邮箱", item.Email);
  3104. AddSingleLinkRow(builder, fontName, labelW, usableWidth - labelW, "官方网站", item.SiteUrl);
  3105. AddSingleLinkRow(builder, fontName, labelW, usableWidth - labelW, "最新动态", item.PostUrl);
  3106. AddFullWidthRow(builder, fontName, labelW, usableWidth - labelW, "推荐等级", item.RecLevel);
  3107. AddFullWidthRow(builder, fontName, labelW, usableWidth - labelW, "经营范围", item.Scope);
  3108. AddFullWidthRow(builder, fontName, labelW, usableWidth - labelW, "对接建议", item.IntgAdvice);
  3109. // 表格样式
  3110. table.SetBorders(Aspose.Words.LineStyle.Single, 0.5, Color.FromArgb(230, 230, 230));
  3111. table.AutoFit(AutoFitBehavior.FixedColumnWidths);
  3112. table.AllowAutoFit = false;
  3113. table.PreferredWidth = PreferredWidth.FromPoints(usableWidth);
  3114. builder.EndTable();
  3115. builder.InsertParagraph();
  3116. builder.InsertParagraph();
  3117. }
  3118. // 保存逻辑
  3119. string fileName = $"{invAiInfo.InvName}_Professional.docx";
  3120. string filePath = Path.Combine(AppSettingsHelper.Get("InvitationAIAssistBasePath"), fileName);
  3121. doc.Save(filePath, Aspose.Words.SaveFormat.Docx);
  3122. return Ok(JsonView(true, "生成成功", new { Url = $"{AppSettingsHelper.Get("WordBaseUrl")}/{AppSettingsHelper.Get("InvitationAIAssistFtpPath")}/{fileName}" }));
  3123. }
  3124. #region 15.12 适配助手方法
  3125. private void AddSingleRow(DocumentBuilder builder, string font, double labelW, double contentW, string label, string value)
  3126. {
  3127. // 标签
  3128. builder.InsertCell();
  3129. builder.CellFormat.Width = labelW;
  3130. builder.ParagraphFormat.Alignment = ParagraphAlignment.Right;
  3131. builder.Font.Name = font;
  3132. builder.Font.Size = 9;
  3133. builder.Font.Bold = false;
  3134. builder.Font.Color = Color.FromArgb(120, 120, 120);
  3135. builder.Write(label);
  3136. // 内容
  3137. builder.InsertCell();
  3138. builder.CellFormat.Width = contentW;
  3139. builder.CellFormat.HorizontalMerge = CellMerge.First;
  3140. builder.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  3141. builder.Font.Size = 10;
  3142. builder.Font.Bold = false;
  3143. builder.Font.Color = Color.FromArgb(60, 60, 60);
  3144. builder.Write(string.IsNullOrEmpty(value) ? "—" : value);
  3145. // 合并剩余列
  3146. builder.InsertCell();
  3147. builder.CellFormat.HorizontalMerge = CellMerge.Previous;
  3148. builder.InsertCell();
  3149. builder.CellFormat.HorizontalMerge = CellMerge.Previous;
  3150. builder.EndRow();
  3151. builder.CellFormat.HorizontalMerge = CellMerge.None;
  3152. }
  3153. private void AddSingleLinkRow(DocumentBuilder builder, string font, double labelW, double contentW, string label, string url)
  3154. {
  3155. builder.InsertCell();
  3156. builder.CellFormat.Width = labelW;
  3157. builder.ParagraphFormat.Alignment = ParagraphAlignment.Right;
  3158. builder.Font.Size = 9;
  3159. builder.Font.Bold = false;
  3160. builder.Font.Color = Color.FromArgb(120, 120, 120);
  3161. builder.Write(label);
  3162. builder.InsertCell();
  3163. builder.CellFormat.Width = contentW;
  3164. builder.CellFormat.HorizontalMerge = CellMerge.First;
  3165. builder.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  3166. if (!string.IsNullOrEmpty(url) && url.StartsWith("http"))
  3167. {
  3168. builder.Font.Size = 10;
  3169. builder.Font.Color = Color.FromArgb(0, 102, 204);
  3170. builder.Font.Underline = Underline.None;
  3171. builder.InsertHyperlink(url, url, false);
  3172. }
  3173. else
  3174. {
  3175. builder.Font.Color = Color.FromArgb(60, 60, 60);
  3176. builder.Write("—");
  3177. }
  3178. builder.InsertCell();
  3179. builder.CellFormat.HorizontalMerge = CellMerge.Previous;
  3180. builder.InsertCell();
  3181. builder.CellFormat.HorizontalMerge = CellMerge.Previous;
  3182. builder.EndRow();
  3183. builder.CellFormat.HorizontalMerge = CellMerge.None;
  3184. }
  3185. private void AddFullWidthRow(DocumentBuilder builder, string font, double lw, double cw, string label, string value)
  3186. {
  3187. // 标签
  3188. builder.InsertCell();
  3189. builder.CellFormat.Width = lw;
  3190. builder.ParagraphFormat.Alignment = ParagraphAlignment.Right;
  3191. builder.Font.Size = 9;
  3192. builder.Font.Bold = false;
  3193. builder.Font.Color = Color.FromArgb(120, 120, 120);
  3194. builder.Write(label);
  3195. // 内容
  3196. builder.InsertCell();
  3197. builder.CellFormat.Width = cw;
  3198. builder.CellFormat.HorizontalMerge = CellMerge.First;
  3199. builder.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  3200. builder.Font.Size = 10;
  3201. builder.Font.Bold = false;
  3202. builder.Font.Color = Color.FromArgb(60, 60, 60);
  3203. builder.Write(string.IsNullOrEmpty(value) ? "—" : value);
  3204. builder.InsertCell();
  3205. builder.CellFormat.HorizontalMerge = CellMerge.Previous;
  3206. builder.InsertCell();
  3207. builder.CellFormat.HorizontalMerge = CellMerge.Previous;
  3208. builder.EndRow();
  3209. builder.CellFormat.HorizontalMerge = CellMerge.None;
  3210. }
  3211. #endregion
  3212. /// <summary>
  3213. /// 商邀资料AI 生成邮件
  3214. /// </summary>
  3215. /// <returns></returns>
  3216. [HttpPost]
  3217. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3218. public async Task<IActionResult> InvitationAIGenerateEmail(InvitationAIGenerateEmailDto dto)
  3219. {
  3220. if (dto.Id < 1) return Ok(JsonView(false, "请选择保存的团组"));
  3221. if (dto.CurrUserId < 1) return Ok(JsonView(false, "请传入用户Id"));
  3222. if (dto.Guids == null || !dto.Guids.Any()) return Ok(JsonView(false, "请传入需要生成邮件的单位列表"));
  3223. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>()
  3224. .Where(x => x.Id == dto.Id)
  3225. .FirstAsync();
  3226. if (invAiInfo == null) return Ok(JsonView(false, "数据信息为空"));
  3227. var dataList = invAiInfo?.AiCrawledDetails;
  3228. if (dataList == null) return Ok(JsonView(false, "邀请方数据信息为空"));
  3229. var clientInfoSources = dataList.Where(x => dto.Guids.Contains(x.Guid)).ToList();
  3230. var clientInfos = clientInfoSources.Select(x => new AICreateEmailInfo()
  3231. {
  3232. Guid = x.Guid,
  3233. NameCn = x.NameCn,
  3234. Scope = x.Scope,
  3235. Subject = "",
  3236. Content = ""
  3237. }).ToList();
  3238. if (clientInfos == null || !clientInfos.Any()) return Ok(JsonView(false, "邀请单位信息为空"));
  3239. var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>()
  3240. .Where(x => x.IsDel == 0 && x.Id == invAiInfo.GroupId)
  3241. .Select(x => new { x.TeamName, x.VisitPurpose,x.VisitDate})
  3242. .FirstAsync();
  3243. string operatorName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
  3244. string pormpt = $@"
  3245. # Role
  3246. 你是一位精通国际政企关系的【首席联络官】。你具备极强的行业分析能力,能通过 [SourceEntity] 的名称自动检索并推导其行政职能与行业地位,并以此撰写具有战略高度、语调优雅的正式商务邮件。
  3247. # Intelligence Task: Source Profiling
  3248. 在生成邮件前,请先执行以下逻辑:
  3249. 1. **职能推导**:基于 [SourceEntity] 的名称,自动识别其在所属领域的具体行政职能与政策影响力。
  3250. 2. **战略对齐**:将其职能与全球大趋势(如:Sustainable Urbanization, Digital Transformation, Carbon Neutrality)挂钩,作为邮件第二段的叙事背景。
  3251. # [RICH_TEXT_STANDARDS_FOR_QUILL]
  3252. - **Prohibited Tags**: 绝对禁止包含 <html>, <body>, <head>, <!DOCTYPE>, <hr>, <style>。
  3253. - **Whitelisted Tags**: 仅允许使用 <h3> (用于主题), <p> (用于段落), <ul>, <li>, <strong>, <br>。
  3254. - **Structural Integrity**:
  3255. - 严禁出现裸露文本,所有段落必须由 <p> 包裹。
  3256. - 列表必须使用标准 <ul><li> 嵌套结构。
  3257. - **No Markdown**: 严禁在 Content 中出现 ###, **, --- 等 Markdown 符号。
  3258. # Reference Model (Few-Shot Example)
  3259. 在生成时,请严格参考以下范例的【语气】、【五段式结构】和【外交辞令】:
  3260. - Subject: Official Study Visit Inquiry – [Delegation Name] ([Date])
  3261. - Para 1: ""On behalf of [SourceEntity], I am writing to formally propose...""
  3262. - Para 2: ""As a pivotal megacity [AI根据Source地位补全]... we recognize [Target]’s leadership in...""
  3263. - Para 3: ""We are particularly keen to explore... [基于Target经营范围推导的3个技术点]...""
  3264. - Para 4: ""We propose a 2–3 day visit... during the week of [Logistics]...""
  3265. - Para 5: ""Enclosed please find the [PascalCase_File]...""
  3266. # Task
  3267. 根据 [TargetList] 中每个单位的【经营范围】,为 [SourceEntity] 生成独立的英文访问请求邮件。
  3268. # Inputs
  3269. - [SourceEntity]: [{invAiInfo.EntryInfo?.OriginUnit ?? ""}]
  3270. - [VisitPurpose]: [{groupInfo?.VisitPurpose}]
  3271. - [TargetList]: [{JsonConvert.SerializeObject(clientInfos)}]
  3272. - [Logistics]: [{groupInfo?.VisitDate.ToString("yyyy-MM-dd")}]
  3273. # Execution Logic (Chain of Thought)
  3274. 1. **Scope-to-Focus Analysis**:
  3275. - 深入分析每个 Target 的【经营范围】。
  3276. - 自动推导 3 个与 [VisitPurpose] 高度对齐的专业考察点(如:Policy Frameworks, Technical Standards, Operational Case Studies)。
  3277. 2. **Modular Drafting**:
  3278. - 必须严格遵循参考范例的 5 段式逻辑。
  3279. - 针对不同职能属性(监管/技术/运营)动态微调邮件主题(Subject)。
  3280. 3. **No Personnel Reference**: 严禁提及“名单、人数、成员、审核中”等任何具体人员信息,保持机构对等对话的高度。
  3281. # Constraints & Standards
  3282. - **Tone**: Formal, Strategic, and Executive (庄重、具战略高度、执行力强)。
  3283. - **Naming Protocol**: 附件引用统一使用 `JointVisitAgenda`, `StrategicInquiryBrief` (PascalCase)。
  3284. - **Escaping**: 必须对 HTML 内部的所有双引号进行严格转义(\""),确保 JSON 字符串合法。
  3285. - **Output Format**: 仅输出一个合规的 JSON 数组,不包含任何解释性文字。
  3286. - **Field Mapping**:
  3287. - `Guid`: 原样保留。
  3288. - `NameCn`: 原样保留。
  3289. - `Scope`: 原样保留。
  3290. - `Subject`: 动态生成的英文主题。
  3291. - `Content`: 包含 QUILL的英文正文。
  3292. # JSON Structure Template
  3293. [
  3294. {{{{
  3295. ""Guid"": ""ID"",
  3296. ""NameCn"": ""Entity Name"",
  3297. ""Scope"": ""Original Scope Description"",
  3298. ""Subject"": ""Dynamic English Subject Line"",
  3299. ""Content"": ""<h3>Subject: ...</h3><p>Dear Leadership Team of <strong>[Target]</strong>,</p><p>On behalf of <strong>[SourceEntity]</strong>, I am writing to propose...</p><ul><li><strong>Focus Area:</strong> Technical analysis of...</li></ul><p>Sincerely,<br><strong>Office of the Chief Liaison</strong><br>[SourceEntity]</p>""
  3300. }}}}
  3301. ]";
  3302. string response = string.Empty;
  3303. try
  3304. {
  3305. response = await _hunyuanService.ChatCompletionsHunyuan_t1_latestAsync(pormpt);
  3306. }
  3307. catch (HttpRequestException ex)
  3308. {
  3309. _logger.LogError(ex, "网络连接失败,无法调用混元API");
  3310. return Ok(JsonView(false, $"网络连接异常,请检查网络后重试!Ex:{ex.Message}"));
  3311. }
  3312. catch (TaskCanceledException ex)
  3313. {
  3314. _logger.LogError(ex, "请求超时");
  3315. return Ok(JsonView(false, $"AI 响应超时,请稍后再试!Ex:{ex.Message}"));
  3316. }
  3317. catch (TencentCloudSDKException ex)
  3318. {
  3319. // 记录完整日志
  3320. _logger.LogError(ex, "腾讯云API调用失败 | 错误码: {ErrorCode} | 请求ID: {RequestId}", ex.ErrorCode, ex.RequestId);
  3321. // 根据错误码做差异化处理
  3322. if (ex.ErrorCode != null && ex.ErrorCode == "AuthFailure.SignatureExpire")
  3323. {
  3324. return Ok(JsonView(false, $"系统时间异常,请同步时间后重试!Ex:{ex.Message}"));
  3325. }
  3326. else if (ex.ErrorCode != null && ex.ErrorCode.StartsWith("Unauthorized"))
  3327. {
  3328. return Ok(JsonView(false, $"当前账号无权限访问该服务!Ex:{ex.Message}"));
  3329. }
  3330. else
  3331. {
  3332. return Ok(JsonView(false, $"腾讯云服务调用失败,请稍后重试!Ex:{ex.Message}"));
  3333. }
  3334. }
  3335. catch (Exception ex)
  3336. {
  3337. _logger.LogError(ex, "未知错误,调用混元API失败");
  3338. return Ok(JsonView(false, $"未知错误,调用混元API失败!Ex:{ex.Message}"));
  3339. }
  3340. var hunyuanAIEmailDatas = new List<AICreateEmailInfo>();
  3341. if (!string.IsNullOrWhiteSpace(response))
  3342. {
  3343. // 预处理:过滤 AI 可能返回的 Markdown 标记
  3344. string cleanJson = response.Trim();
  3345. if (cleanJson.StartsWith("```json"))
  3346. cleanJson = cleanJson.Substring(7, cleanJson.Length - 10).Trim();
  3347. else if (cleanJson.StartsWith("```"))
  3348. cleanJson = cleanJson.Substring(3, cleanJson.Length - 6).Trim();
  3349. try
  3350. {
  3351. // 解析并注入 Source 标识
  3352. hunyuanAIEmailDatas = JsonConvert.DeserializeObject<List<AICreateEmailInfo>>(cleanJson);
  3353. }
  3354. catch (JsonException ex)
  3355. {
  3356. // 记录日志并考虑 fallback 策略
  3357. _logger.LogError(ex, "Hunyuan AI 响应解析失败。原始数据:{Response}", response);
  3358. }
  3359. }
  3360. if (hunyuanAIEmailDatas == null || !hunyuanAIEmailDatas.Any())
  3361. {
  3362. return Ok(JsonView(false, "Hunyuan AI 生成的邮件为空"));
  3363. }
  3364. // 数据邮件存储在数据库
  3365. var msgSb = new StringBuilder();
  3366. foreach (var client in clientInfoSources)
  3367. {
  3368. var aiEmailInfo = hunyuanAIEmailDatas.Where(x => x.Guid == client.Guid).FirstOrDefault();
  3369. if (aiEmailInfo == null)
  3370. {
  3371. msgSb.AppendLine($"{client.NameCn}: 邮件AI生成失败!");
  3372. continue;
  3373. }
  3374. client.EmailInfo.Status = 2; // AI已生成
  3375. client.EmailInfo.EmailTitle = aiEmailInfo.Subject;
  3376. client.EmailInfo.EmailContent = aiEmailInfo.Content;
  3377. client.EmailInfo.Operator = operatorName;
  3378. client.EmailInfo.OperatedAt = DateTime.Now;
  3379. msgSb.AppendLine($"{client.NameCn}: 邮件AI生成成功!");
  3380. }
  3381. // 先删除原有数据中对应的单位数据
  3382. invAiInfo.AiCrawledDetails = invAiInfo.AiCrawledDetails.Where(x => !dto.Guids.Contains(x.Guid)).ToList();
  3383. // 再添加AI生成的邮件数据
  3384. invAiInfo.AiCrawledDetails.AddRange(clientInfoSources);
  3385. // 排序
  3386. invAiInfo.AiCrawledDetails = invAiInfo.AiCrawledDetails.OrderByDescending(x => x.OperatedAt).ToList();
  3387. var update = await _sqlSugar.Updateable(invAiInfo).UpdateColumns(x => x.AiCrawledDetails).ExecuteCommandAsync();
  3388. if (update < 1)
  3389. {
  3390. return Ok(JsonView(false, $"邮件AI生成,数据更新失败!"));
  3391. }
  3392. return Ok(JsonView(true, msgSb.ToString()));
  3393. }
  3394. /// <summary>
  3395. /// 商邀资料AI 生成邮件(SSE流式推送)
  3396. /// </summary>
  3397. /// <returns></returns>
  3398. [HttpPost]
  3399. public async Task InvitationAIGenerateEmailStream([FromBody] InvitationAIGenerateEmailDto dto)
  3400. {
  3401. var response = HttpContext.Response;
  3402. response.Headers.Add("Content-Type", "text/event-stream");
  3403. response.Headers.Add("Cache-Control", "no-cache");
  3404. response.Headers.Add("Connection", "keep-alive");
  3405. response.Headers.Add("X-Accel-Buffering", "no");
  3406. async Task SendStep(int progress, string msg, object data = null)
  3407. {
  3408. var payload = JsonConvert.SerializeObject(new
  3409. {
  3410. progress,
  3411. message = msg,
  3412. data,
  3413. operatedAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
  3414. });
  3415. await response.WriteAsync($"data: {payload}\n\n");
  3416. await response.Body.FlushAsync();
  3417. }
  3418. try
  3419. {
  3420. // 1. 基础校验与资源加载 (Progress: 5%)
  3421. if (dto.Id < 1 || dto.Guids == null || !dto.Guids.Any())
  3422. {
  3423. await SendStep(-1, "请求参数不完整,请选择单位");
  3424. return;
  3425. }
  3426. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>().Where(x => x.Id == dto.Id).FirstAsync();
  3427. if (invAiInfo?.AiCrawledDetails == null)
  3428. {
  3429. await SendStep(-1, "基础商邀资料不存在");
  3430. return;
  3431. }
  3432. await SendStep(10, "正在分析考察团组背景与访问意图...");
  3433. // 2. 准备 AI 上下文数据 (Progress: 15%)
  3434. var clientInfoSources = invAiInfo.AiCrawledDetails.Where(x => dto.Guids.Contains(x.Guid)).ToList();
  3435. var clientInfosForAI = clientInfoSources.Select(x => new AICreateEmailInfo()
  3436. {
  3437. Guid = x.Guid,
  3438. NameCn = x.NameCn,
  3439. Scope = x.Scope
  3440. }).ToList();
  3441. var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>()
  3442. .Where(x => x.IsDel == 0 && x.Id == invAiInfo.GroupId)
  3443. .Select(x => new { x.TeamName, x.VisitPurpose, x.VisitDate })
  3444. .FirstAsync();
  3445. string operatorName = await _sqlSugar.Queryable<Sys_Users>()
  3446. .Where(x => x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
  3447. // 3. 构建 Prompt 并调用 AI (Progress: 25%)
  3448. await SendStep(30, $"首席联络官已就位,正在为 {clientInfosForAI.Count} 家单位撰写定制化正式邮件...");
  3449. // 此处沿用你原有的庞大 Prompt 逻辑
  3450. string pormpt = $@"
  3451. # Role
  3452. 你是一位精通国际政企关系的【首席联络官】。你具备极强的行业分析能力,能通过 [SourceEntity] 的名称自动检索并推导其行政职能与行业地位,并以此撰写具有战略高度、语调优雅的正式商务邮件。
  3453. # Intelligence Task: Source Profiling
  3454. 在生成邮件前,请先执行以下逻辑:
  3455. 1. **职能推导**:基于 [SourceEntity] 的名称,自动识别其在所属领域的具体行政职能与政策影响力。
  3456. 2. **战略对齐**:将其职能与全球大趋势(如:Sustainable Urbanization, Digital Transformation, Carbon Neutrality)挂钩,作为邮件第二段的叙事背景。
  3457. # [RICH_TEXT_STANDARDS_FOR_QUILL]
  3458. - **Prohibited Tags**: 绝对禁止包含 <html>, <body>, <head>, <!DOCTYPE>, <hr>, <style>。
  3459. - **Whitelisted Tags**: 仅允许使用 <h3> (用于主题), <p> (用于段落), <ul>, <li>, <strong>, <br>。
  3460. - **Structural Integrity**:
  3461. - 严禁出现裸露文本,所有段落必须由 <p> 包裹。
  3462. - 列表必须使用标准 <ul><li> 嵌套结构。
  3463. - **No Markdown**: 严禁在 Content 中出现 ###, **, --- 等 Markdown 符号。
  3464. # Reference Model (Few-Shot Example)
  3465. 在生成时,请严格参考以下范例的【语气】、【五段式结构】和【外交辞令】:
  3466. - Subject: Official Study Visit Inquiry – [Delegation Name] ([Date])
  3467. - Para 1: ""On behalf of [SourceEntity], I am writing to formally propose...""
  3468. - Para 2: ""As a pivotal megacity [AI根据Source地位补全]... we recognize [Target]’s leadership in...""
  3469. - Para 3: ""We are particularly keen to explore... [基于Target经营范围推导的3个技术点]...""
  3470. - Para 4: ""We propose a 2–3 day visit... during the week of [Logistics]...""
  3471. - Para 5: ""Enclosed please find the [PascalCase_File]...""
  3472. # Task
  3473. 根据 [TargetList] 中每个单位的【经营范围】,为 [SourceEntity] 生成独立的英文访问请求邮件。
  3474. # Inputs
  3475. - [SourceEntity]: [{invAiInfo.EntryInfo?.OriginUnit ?? ""}]
  3476. - [VisitPurpose]: [{groupInfo?.VisitPurpose}]
  3477. - [TargetList]: [{JsonConvert.SerializeObject(clientInfosForAI)}]
  3478. - [Logistics]: [{groupInfo?.VisitDate.ToString("yyyy-MM-dd")}]
  3479. # Execution Logic (Chain of Thought)
  3480. 1. **Scope-to-Focus Analysis**:
  3481. - 深入分析每个 Target 的【经营范围】。
  3482. - 自动推导 3 个与 [VisitPurpose] 高度对齐的专业考察点(如:Policy Frameworks, Technical Standards, Operational Case Studies)。
  3483. 2. **Modular Drafting**:
  3484. - 必须严格遵循参考范例的 5 段式逻辑。
  3485. - 针对不同职能属性(监管/技术/运营)动态微调邮件主题(Subject)。
  3486. 3. **No Personnel Reference**: 严禁提及“名单、人数、成员、审核中”等任何具体人员信息,保持机构对等对话的高度。
  3487. # Constraints & Standards
  3488. - **Tone**: Formal, Strategic, and Executive (庄重、具战略高度、执行力强)。
  3489. - **Naming Protocol**: 附件引用统一使用 `JointVisitAgenda`, `StrategicInquiryBrief` (PascalCase)。
  3490. - **Escaping**: 必须对 HTML 内部的所有双引号进行严格转义(\""),确保 JSON 字符串合法。
  3491. - **Output Format**: 仅输出一个合规的 JSON 数组,不包含任何解释性文字。
  3492. - **Field Mapping**:
  3493. - `Guid`: 原样保留。
  3494. - `NameCn`: 原样保留。
  3495. - `Scope`: 原样保留。
  3496. - `Subject`: 动态生成的英文主题。
  3497. - `Content`: 包含 QUILL的英文正文。
  3498. # JSON Structure Template
  3499. [
  3500. {{{{
  3501. ""Guid"": ""ID"",
  3502. ""NameCn"": ""Entity Name"",
  3503. ""Scope"": ""Original Scope Description"",
  3504. ""Subject"": ""Dynamic English Subject Line"",
  3505. ""Content"": ""<h3>Subject: ...</h3><p>Dear Leadership Team of <strong>[Target]</strong>,</p><p>On behalf of <strong>[SourceEntity]</strong>, I am writing to propose...</p><ul><li><strong>Focus Area:</strong> Technical analysis of...</li></ul><p>Sincerely,<br><strong>Office of the Chief Liaison</strong><br>[SourceEntity]</p>""
  3506. }}}}
  3507. ]";
  3508. // 调用 AI (此处为阻塞式等待 AI 结果,若混元支持 Stream 可进一步拆解)
  3509. string aiResponse = await _hunyuanService.ChatCompletionsHunyuan_t1_latestAsync(pormpt);
  3510. await SendStep(80, "邮件初稿已生成,正在进行 HTML 格式校验与转义处理...");
  3511. // 4. 解析结果 (Progress: 85%)
  3512. var hunyuanAIEmailDatas = new List<AICreateEmailInfo>();
  3513. if (!string.IsNullOrWhiteSpace(aiResponse))
  3514. {
  3515. // 预处理:过滤 AI 可能返回的 Markdown 标记
  3516. string cleanJson = aiResponse.Trim();
  3517. if (cleanJson.StartsWith("```json"))
  3518. cleanJson = cleanJson.Substring(7, cleanJson.Length - 10).Trim();
  3519. else if (cleanJson.StartsWith("```"))
  3520. cleanJson = cleanJson.Substring(3, cleanJson.Length - 6).Trim();
  3521. try
  3522. {
  3523. // 解析并注入 Source 标识
  3524. hunyuanAIEmailDatas = JsonConvert.DeserializeObject<List<AICreateEmailInfo>>(cleanJson);
  3525. }
  3526. catch (JsonException ex)
  3527. {
  3528. // 记录日志并考虑 fallback 策略
  3529. _logger.LogError(ex, "Hunyuan AI 响应解析失败。原始数据:{Response}", aiResponse);
  3530. }
  3531. }
  3532. if (hunyuanAIEmailDatas == null || !hunyuanAIEmailDatas.Any())
  3533. {
  3534. await SendStep(-1, "AI 格式解析失败,请尝试重新生成");
  3535. return;
  3536. }
  3537. // 5. 更新数据模型 (Progress: 90%)
  3538. foreach (var client in clientInfoSources)
  3539. {
  3540. var aiEmail = hunyuanAIEmailDatas.FirstOrDefault(x => x.Guid == client.Guid);
  3541. if (aiEmail != null)
  3542. {
  3543. client.EmailInfo.Status = 2; // 已生成
  3544. client.EmailInfo.EmailTitle = aiEmail.Subject;
  3545. client.EmailInfo.EmailContent = aiEmail.Content;
  3546. client.EmailInfo.Operator = operatorName;
  3547. client.EmailInfo.OperatedAt = DateTime.Now;
  3548. }
  3549. }
  3550. // 6. 数据库持久化 (Progress: 95%)
  3551. // 采用增量更新策略,避免直接 Where 过滤掉其他未选中的数据
  3552. var update = await _sqlSugar.Updateable(invAiInfo).UpdateColumns(x => x.AiCrawledDetails).ExecuteCommandAsync();
  3553. if (update > 0)
  3554. {
  3555. await SendStep(100, "邮件全部生成完毕并已存入团组资料库", invAiInfo.AiCrawledDetails);
  3556. }
  3557. else
  3558. {
  3559. await SendStep(-1, "数据库写入失败,请联系管理员");
  3560. }
  3561. }
  3562. catch (Exception ex)
  3563. {
  3564. _logger.LogError(ex, "邮件生成异常");
  3565. await SendStep(-1, $"生成失败:{ex.Message}");
  3566. }
  3567. finally
  3568. {
  3569. await response.CompleteAsync();
  3570. }
  3571. }
  3572. /// <summary>
  3573. /// 商邀资料AI 邮件保存
  3574. /// </summary>
  3575. /// <returns></returns>
  3576. [HttpPost]
  3577. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3578. public async Task<IActionResult> InvitationAIEmailSave(InvitationAIEmailSaveDto dto)
  3579. {
  3580. if (dto.Id < 1) return Ok(JsonView(false, "请选择保存的团组"));
  3581. if (dto.CurrUserId < 1) return Ok(JsonView(false, "请传入用户Id"));
  3582. if (string.IsNullOrEmpty(dto.Guid)) return Ok(JsonView(false, "请传入Guid"));
  3583. if (string.IsNullOrEmpty(dto.EmailTitle)) return Ok(JsonView(false, "请传入邮件标题"));
  3584. if (string.IsNullOrEmpty(dto.EmailContent)) return Ok(JsonView(false, "请传入邮件内容"));
  3585. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>()
  3586. .Where(x => x.Id == dto.Id)
  3587. .FirstAsync();
  3588. if (invAiInfo == null) return Ok(JsonView(false, "数据信息为空"));
  3589. var dataList = invAiInfo?.AiCrawledDetails;
  3590. if (dataList == null) return Ok(JsonView(false, "邀请方数据信息为空"));
  3591. var editInfo = dataList.Where(x => x.Guid == dto.Guid).FirstOrDefault();
  3592. if (editInfo == null) return Ok(JsonView(false, "邀请方信息为空"));
  3593. var opUserName = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId).Select(x => x.CnName).FirstAsync() ?? "-";
  3594. editInfo.EmailInfo.EmailTitle = dto.EmailTitle;
  3595. editInfo.EmailInfo.EmailContent = dto.EmailContent;
  3596. editInfo.EmailInfo.Operator = opUserName;
  3597. editInfo.EmailInfo.OperatedAt = DateTime.Now;
  3598. var datas = dataList.Where(x => x.Guid != dto.Guid).ToList();
  3599. datas.Add(editInfo);
  3600. // 排序
  3601. invAiInfo.AiCrawledDetails = datas.OrderByDescending(x => x.OperatedAt).ToList();
  3602. var editUpd = await _sqlSugar.Updateable(invAiInfo).UpdateColumns(x => x.AiCrawledDetails).ExecuteCommandAsync();
  3603. if (editUpd < 1)
  3604. {
  3605. return Ok(JsonView(true, "邮件保存失败"));
  3606. }
  3607. return Ok(JsonView(true, "邮件保存成功"));
  3608. }
  3609. /// <summary>
  3610. /// 商邀资料AI 发送邮件(默认当前用户企业微信邮件)
  3611. /// </summary>
  3612. /// <returns></returns>
  3613. [HttpPost]
  3614. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3615. public async Task<IActionResult> InvitationAISeedEmail(InvitationAISeedEmailDto dto)
  3616. {
  3617. if (dto.Id < 1) return Ok(JsonView(false, "请选择发送邮件的团组"));
  3618. if (dto.CurrUserId < 1) return Ok(JsonView(false, "请传入用户Id"));
  3619. if (dto.Guids == null || dto.Guids.Count < 1) return Ok(JsonView(false, "请选择发送邮件的单位"));
  3620. var invAiInfo = await _sqlSugar.Queryable<Res_InvitationAI>()
  3621. .Where(x => x.Id == dto.Id)
  3622. .FirstAsync();
  3623. if (invAiInfo == null) return Ok(JsonView(false, "数据信息为空"));
  3624. var dataList = invAiInfo?.AiCrawledDetails;
  3625. if (dataList == null) return Ok(JsonView(false, "邀请方数据信息为空"));
  3626. var seedInvInfos = dataList.Where(x => dto.Guids.Contains(x.Guid)).ToList();
  3627. if (seedInvInfos == null) Ok(JsonView(false, "发送邮件的邀请方信息为空"));
  3628. var userInfo = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Id == dto.CurrUserId).Select(x => new { x.Email, x.CnName }).FirstAsync();
  3629. if (string.IsNullOrEmpty(userInfo.Email)) Ok(JsonView(false, "当前账号未配置邮箱,请先配置邮箱!"));
  3630. var msgSb = new StringBuilder();
  3631. #region 发送邮件
  3632. foreach (var item in seedInvInfos)
  3633. {
  3634. int seedStatus = 5;
  3635. if (!string.IsNullOrEmpty(item.EmailInfo.EmailTitle) && !string.IsNullOrEmpty(item.EmailInfo.EmailContent))
  3636. {
  3637. try
  3638. {
  3639. var req = new EmailRequestDto()
  3640. {
  3641. ToEmails = new List<string> { item.Email },
  3642. //CcEmails = new List<string> { userInfo.Email },
  3643. //BccEmails = new List<string> { userInfo.Email },
  3644. Subject = item.EmailInfo.EmailTitle,
  3645. Body = item.EmailInfo.EmailContent,
  3646. Files = Array.Empty<IFormFile>()
  3647. };
  3648. var response = await _qiYeWeChatApiService.EmailSendAsync(req);
  3649. if (response.errcode == 0)
  3650. {
  3651. seedStatus = 4;
  3652. item.EmailInfo.Status = seedStatus;
  3653. item.EmailInfo.Operator = userInfo?.CnName ?? "";
  3654. item.EmailInfo.OperatedAt = DateTime.Now;
  3655. msgSb.AppendLine($"{item.NameCn}({item.Email}):邮件发送成功!");
  3656. }
  3657. else
  3658. {
  3659. msgSb.AppendLine($"{item.NameCn}({item.Email}):邮件发送失败(msg:{response.errmsg})");
  3660. }
  3661. }
  3662. catch (Exception ex)
  3663. {
  3664. _logger.LogError(ex, "商邀AI调用企业微信邮件API失败。");
  3665. msgSb.AppendLine($"{item.NameCn}({item.Email}):邮件发送失败(msg:商邀AI调用企业微信邮件API失败。)");
  3666. }
  3667. }
  3668. }
  3669. #endregion
  3670. // 先删除原有数据中对应的单位数据
  3671. invAiInfo.AiCrawledDetails = invAiInfo.AiCrawledDetails.Where(x => !dto.Guids.Contains(x.Guid)).ToList();
  3672. // 再添加AI生成的邮件数据
  3673. invAiInfo.AiCrawledDetails.AddRange(seedInvInfos);
  3674. // 排序
  3675. invAiInfo.AiCrawledDetails = invAiInfo.AiCrawledDetails.OrderByDescending(x=> x.OperatedAt).ToList();
  3676. var update = await _sqlSugar.Updateable(invAiInfo).UpdateColumns(x => x.AiCrawledDetails).ExecuteCommandAsync();
  3677. if (update < 1)
  3678. {
  3679. return Ok(JsonView(false, $"邮件AI发送,数据保存失败!"));
  3680. }
  3681. return Ok(JsonView(true, msgSb.ToString()));
  3682. }
  3683. #endregion
  3684. #region 公务出访
  3685. /// <summary>
  3686. /// 获取团组所有信息,绑定下拉框
  3687. /// </summary>
  3688. /// <param name="dto"></param>
  3689. /// <returns></returns>
  3690. [HttpPost]
  3691. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3692. public async Task<IActionResult> GetGroupAllList(OfficialActivitiesByDiIdDto dto)
  3693. {
  3694. //string groupSql = string.Format("Select * From Grp_DelegationInfo With(NoLock) Where IsDel = 0 Order By CreateTime Desc");
  3695. //List<Grp_DelegationInfo> _DelegationInfos = _sqlSugar.SqlQueryable< Grp_DelegationInfo >(groupSql).ToList();
  3696. var _groupData = await _delegationInfoRep.PostShareGroupInfos(1);
  3697. dynamic groupInfos = null;
  3698. if (_groupData.Code == 0) groupInfos = _groupData.Data;
  3699. var data = _sqlSugar.Queryable<Sys_SetData>().Where(a => a.IsDel == 0).ToList();
  3700. var data1 = data.Where(a => a.STid == 38).Select(x => new { x.Id, x.Name }).ToList();
  3701. var data2 = data.Where(a => a.STid == 101).Select(x => new { x.Id, x.Name }).ToList();
  3702. //张总安排未参与对接
  3703. if (data2.Any(x => x.Name.Equals("张总安排未参与对接")))
  3704. {
  3705. var zhangZong = data2.FirstOrDefault(x => x.Name.Equals("张总安排未参与对接"));
  3706. if (zhangZong != null) data2.Remove(zhangZong);
  3707. data2.Insert(0, zhangZong);
  3708. }
  3709. var data3 = data.Where(a => a.STid == 66).Select(x => new { x.Id, x.Name, x.Remark }).ToList();
  3710. var _DeleFile = _sqlSugar.Queryable<Grp_DeleFile>().Where(a => a.Diid == dto.DiId && a.IsDel == 0 && a.Category == 970).ToList();
  3711. var translatorData = _sqlSugar.Queryable<Res_TranslatorLibrary>().Where(a => a.IsDel == 0).ToList();
  3712. var translatorData1 = _mapper.Map<List<TranslatorView>>(translatorData);
  3713. foreach (var item in translatorData1) EncryptionProcessor.DecryptProperties(item);
  3714. return Ok(JsonView(true,
  3715. "查询成功!",
  3716. new
  3717. {
  3718. Delegation = groupInfos,
  3719. SetData = data1,
  3720. DataSource = data2,
  3721. currencyData = data3,
  3722. DeleFile = _DeleFile,
  3723. TranslatorData = translatorData1
  3724. }));
  3725. }
  3726. /// <summary>
  3727. /// 公务 团组名称 Page List
  3728. /// </summary>
  3729. /// <param name="dto"></param>
  3730. /// <returns></returns>
  3731. [HttpPost]
  3732. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3733. public async Task<IActionResult> OfficialActivitiesGroupNameList(OfficialActivitiesGroupNameListDto dto)
  3734. {
  3735. var sw = Stopwatch.StartNew();
  3736. if (!SharingStaticData.PortTypes.Contains(dto.PortType))
  3737. {
  3738. return Ok(JsonView(false, MsgTips.Port));
  3739. }
  3740. dto.PageIndex = dto.PageIndex == 0 ? 1 : dto.PageIndex;
  3741. dto.PageSize = dto.PageSize == 0 ? 10 : dto.PageSize;
  3742. RefAsync<int> total = 0;
  3743. // 只查询需要的字段,避免Select后再赋值,减少内存占用
  3744. var groupInfos = await _officialActivitiesRep._sqlSugar
  3745. .Queryable<Grp_DelegationInfo>()
  3746. .Where(x => x.IsDel == 0)
  3747. .WhereIF(!string.IsNullOrEmpty(dto.GroupName), x => x.TeamName.Contains(dto.GroupName))
  3748. .OrderByDescending(x => x.VisitDate)
  3749. .Select(x => new Web_ShareGroupInfoView()
  3750. {
  3751. Id = x.Id,
  3752. TeamName = x.TeamName,
  3753. TourCode = x.TourCode,
  3754. ClientName = x.ClientName,
  3755. VisitCountry = x.VisitCountry,
  3756. VisitStartDate = x.VisitStartDate,
  3757. VisitEndDate = x.VisitEndDate,
  3758. VisitDays = x.VisitDays,
  3759. VisitPNumber = x.VisitPNumber
  3760. })
  3761. .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
  3762. if (groupInfos.Count > 0)
  3763. {
  3764. for (int i = 0; i < groupInfos.Count; i++)
  3765. {
  3766. var visitCountry = groupInfos[i].VisitCountry;
  3767. groupInfos[i].VisitCountry = !string.IsNullOrEmpty(visitCountry)
  3768. ? _delegationInfoRep.FormartTeamName(visitCountry)
  3769. : string.Empty;
  3770. }
  3771. }
  3772. sw.Stop();
  3773. return Ok(JsonView(true, $"操作成功!耗时:{sw.ElapsedMilliseconds}ms", groupInfos, total));
  3774. }
  3775. /// <summary>
  3776. /// 公务 翻译人员 Page List
  3777. /// </summary>
  3778. /// <param name="dto"></param>
  3779. /// <returns></returns>
  3780. [HttpPost]
  3781. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3782. public async Task<IActionResult> OfficialActivitiesTranslatorList(OfficialActivitiesTranslatorListDto dto)
  3783. {
  3784. var sw = Stopwatch.StartNew();
  3785. if (!SharingStaticData.PortTypes.Contains(dto.PortType))
  3786. {
  3787. return Ok(JsonView(false, MsgTips.Port));
  3788. }
  3789. dto.PageIndex = dto.PageIndex == 0 ? 1 : dto.PageIndex;
  3790. dto.PageSize = dto.PageSize == 0 ? 10 : dto.PageSize;
  3791. var translatorIds = new List<int>();
  3792. if (!string.IsNullOrEmpty(dto.TranslatorName))
  3793. {
  3794. var translators = await _sqlSugar.Queryable<Res_TranslatorLibrary>()
  3795. .Where(x => x.IsDel == 0 && !string.IsNullOrEmpty(x.Name))
  3796. .Select(x => new { x.Id, x.Name })
  3797. .ToListAsync();
  3798. if (translators.Any())
  3799. {
  3800. foreach (var item in translators)
  3801. {
  3802. var decryptedName = AesEncryptionHelper.Decrypt(item.Name);
  3803. if (!string.IsNullOrEmpty(decryptedName) && decryptedName.Contains(dto.TranslatorName))
  3804. {
  3805. translatorIds.Add(item.Id);
  3806. }
  3807. }
  3808. }
  3809. if (translatorIds.Count == 0)
  3810. {
  3811. sw.Stop();
  3812. return Ok(JsonView(true, $"暂无翻译人员信息!耗时: {sw.ElapsedMilliseconds}ms", Array.Empty<TranslatorView>(), 0));
  3813. }
  3814. }
  3815. RefAsync<int> total = 0;
  3816. var translatorInfos = await _officialActivitiesRep._sqlSugar
  3817. .Queryable<Res_TranslatorLibrary>()
  3818. .Where(x => x.IsDel == 0 && !string.IsNullOrEmpty(x.Name))
  3819. .WhereIF(translatorIds != null && translatorIds.Count > 0, x => translatorIds.Contains(x.Id))
  3820. .OrderByDescending(x => x.CreateTime)
  3821. .Select(x => new TranslatorView()
  3822. {
  3823. Id = x.Id,
  3824. Area = x.Area,
  3825. Name = x.Name,
  3826. Sex = x.Sex,
  3827. Tel = x.Tel,
  3828. Email = x.Email,
  3829. WechatNo = x.WechatNo,
  3830. OtherSocialAccounts = x.OtherSocialAccounts,
  3831. Language = x.Language,
  3832. Price = x.Price,
  3833. Currency = x.Currency,
  3834. })
  3835. .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
  3836. for (int i = 0; i < translatorInfos.Count; i++)
  3837. {
  3838. EncryptionProcessor.DecryptProperties(translatorInfos[i]);
  3839. }
  3840. sw.Stop();
  3841. string msg = translatorInfos.Count == 0 ? $"暂无您查询的翻译人员信息!耗时: {sw.ElapsedMilliseconds}ms" : $"操作成功!耗时: {sw.ElapsedMilliseconds}ms";
  3842. return Ok(JsonView(true, msg, translatorInfos, total));
  3843. }
  3844. /// <summary>
  3845. /// 公务 绑定下拉框
  3846. /// </summary>
  3847. /// <param name="dto"></param>
  3848. /// <returns></returns>
  3849. [HttpPost]
  3850. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3851. public async Task<IActionResult> OfficialActivitiesInitDatabase(OfficialActivitiesByDiIdDto dto)
  3852. {
  3853. var data = _sqlSugar.Queryable<Sys_SetData>().Where(a => a.IsDel == 0).ToList();
  3854. var data1 = data.Where(a => a.STid == 38).Select(x => new { x.Id, x.Name }).ToList();
  3855. var data2 = data.Where(a => a.STid == 101).Select(x => new { x.Id, x.Name }).ToList();
  3856. //张总安排未参与对接
  3857. if (data2.Any(x => x.Name.Equals("张总安排未参与对接")))
  3858. {
  3859. var zhangZong = data2.FirstOrDefault(x => x.Name.Equals("张总安排未参与对接"));
  3860. if (zhangZong != null) data2.Remove(zhangZong);
  3861. data2.Insert(0, zhangZong);
  3862. }
  3863. var data3 = data.Where(a => a.STid == 66).Select(x => new { x.Id, x.Name, x.Remark }).ToList();
  3864. var _DeleFile = _sqlSugar.Queryable<Grp_DeleFile>().Where(a => a.Diid == dto.DiId && a.IsDel == 0 && a.Category == 970).ToList();
  3865. return Ok(JsonView(true,
  3866. "查询成功!",
  3867. new
  3868. {
  3869. SetData = data1,
  3870. DataSource = data2,
  3871. currencyData = data3,
  3872. DeleFile = _DeleFile
  3873. }));
  3874. }
  3875. /// <summary>
  3876. /// 公务List
  3877. /// </summary>
  3878. /// <param name="dto"></param>
  3879. /// <returns></returns>
  3880. [HttpPost]
  3881. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3882. public async Task<IActionResult> QueryOfficialActivitiesByDiId(OfficialActivitiesByDiIdDto dto)
  3883. {
  3884. return Ok(await _officialActivitiesRep.QueryOfficialActivitiesByDiId(dto));
  3885. }
  3886. /// <summary>
  3887. /// 根据公务出访数据Id查询数据
  3888. /// </summary>
  3889. /// <param name="dto"></param>
  3890. /// <returns></returns>
  3891. [HttpPost]
  3892. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3893. public async Task<IActionResult> QueryOfficialActivitiesById(OfficialActivitiesDiIdDto dto)
  3894. {
  3895. Result groupData = await _officialActivitiesRep.QueryOfficialActivitiesById(dto);
  3896. if (groupData.Code != 0)
  3897. {
  3898. return Ok(JsonView(false, groupData.Msg));
  3899. }
  3900. return Ok(JsonView(true, groupData.Msg, groupData.Data));
  3901. }
  3902. /// <summary>
  3903. /// 公务出访操作(Status:1.新增,2.修改)
  3904. /// </summary>
  3905. /// <param name="dto"></param>
  3906. /// <returns></returns>
  3907. [HttpPost]
  3908. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3909. public async Task<IActionResult> OpOfficialActivities(OpOfficialActivitiesDto dto)
  3910. {
  3911. Result groupData = await _officialActivitiesRep.OpOfficialActivities(dto);
  3912. if (groupData.Code != 0)
  3913. {
  3914. return Ok(JsonView(StatusCodes.Status400BadRequest, groupData.Msg, new { Id = 0 }));
  3915. }
  3916. try
  3917. {
  3918. //公务出访变更发送通知
  3919. await AppNoticeLibrary.SendUserMsg_GroupShare_ToOP(dto.DiId, dto.CreateUserId);
  3920. }
  3921. catch (Exception ex)
  3922. {
  3923. //抄送日志
  3924. }
  3925. return Ok(JsonView(true, groupData.Msg, groupData.Data));
  3926. }
  3927. /// <summary>
  3928. /// 上传文件(邮件截图)
  3929. /// </summary>
  3930. /// <param name="dto"></param>
  3931. /// <returns></returns>
  3932. [HttpPost]
  3933. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  3934. public async Task<IActionResult> OfficialActivitiesUploadFiles([FromForm] OfficialActivitiesUploadFilesDto dto)
  3935. {
  3936. string networkPath = AppSettingsHelper.Get("GrpFileBaseUrl");
  3937. string localPath = AppSettingsHelper.Get("GrpFileBasePath");
  3938. string ptfPath = AppSettingsHelper.Get("GrpFileFtpPath");
  3939. if (dto.diId < 1 || dto.currUserId < 1)
  3940. {
  3941. return Ok(JsonView(false, "参数有误,上传失败!"));
  3942. }
  3943. if (dto.files == null || dto.files.Count < 1)
  3944. {
  3945. return Ok(JsonView(false, "文件为空,上传失败!"));
  3946. }
  3947. string localFileDir = $"{localPath}{ptfPath}";
  3948. List<string> fileUrls = new List<string>();
  3949. string[] failFiles = new string[] { };
  3950. foreach (var file in dto.files)
  3951. {
  3952. //文件名称
  3953. string[] fileNameArray = file.FileName.Split(".");
  3954. string projectFileName = $"{fileNameArray[0].ToString().Replace("-", "_").Replace("/", "_")}{DateTime.UtcNow:yyyyMMddHHmmss}.{fileNameArray[1]}";
  3955. //上传的文件的路径
  3956. string filePath = $@"{localPath}公务相关文件";
  3957. if (!Directory.Exists(filePath))
  3958. {
  3959. Directory.CreateDirectory(filePath);
  3960. }
  3961. var path = Path.Combine(filePath, projectFileName);
  3962. //using var stream = new FileStream(path, FileMode.Create);
  3963. //await file.CopyToAsync(stream);
  3964. try
  3965. {
  3966. using (FileStream fs = System.IO.File.Create(path))
  3967. {
  3968. file.CopyTo(fs);
  3969. fs.Flush();
  3970. }
  3971. fileUrls.Add($"/{ptfPath}公务相关文件/{projectFileName}");
  3972. }
  3973. catch (Exception ex)
  3974. {
  3975. failFiles.Append(file.FileName);
  3976. }
  3977. }
  3978. var oaInfo = await _sqlSugar.Queryable<Res_OfficialActivities>().Where(x => x.Id == dto.id).FirstAsync();
  3979. List<string> files = new List<string>();
  3980. var status = false;
  3981. var _oaInfo = new Res_OfficialActivities()
  3982. {
  3983. DiId = dto.diId,
  3984. ScreenshotOfMailUrl = JsonConvert.SerializeObject(fileUrls),
  3985. IsDel = 0,
  3986. CreateUserId = dto.currUserId,
  3987. CreateTime = DateTime.Now
  3988. };
  3989. if (oaInfo == null)
  3990. {
  3991. var id = await _sqlSugar.Insertable<Res_OfficialActivities>(_oaInfo)
  3992. .ExecuteReturnIdentityAsync();
  3993. if (id > 0)
  3994. {
  3995. status = true;
  3996. dto.id = id;
  3997. }
  3998. }
  3999. else
  4000. {
  4001. var oldFiles = string.IsNullOrEmpty(oaInfo.ScreenshotOfMailUrl)
  4002. ? new List<string>()
  4003. : JsonConvert.DeserializeObject<List<string>>(oaInfo.ScreenshotOfMailUrl);
  4004. if (oldFiles.Count > 0)
  4005. {
  4006. fileUrls.AddRange(oldFiles);
  4007. }
  4008. fileUrls = fileUrls.Distinct().ToList();
  4009. if (fileUrls.Count > 0)
  4010. {
  4011. var upd = await _sqlSugar.Updateable<Res_OfficialActivities>()
  4012. .SetColumns(x => x.ScreenshotOfMailUrl == JsonConvert.SerializeObject(fileUrls))
  4013. .Where(x => x.Id == dto.id)
  4014. .ExecuteCommandAsync();
  4015. if (upd > 0) status = true;
  4016. }
  4017. }
  4018. List<string> returnFileUrls = new List<string>();
  4019. fileUrls.ForEach(x =>
  4020. {
  4021. returnFileUrls.Add($"{networkPath}{x}");
  4022. });
  4023. if (status)
  4024. {
  4025. string msg = "操作成功!";
  4026. if (failFiles.Length > 1)
  4027. {
  4028. foreach (var item in failFiles)
  4029. {
  4030. msg += $"{failFiles}、";
  4031. }
  4032. msg = msg.Substring(0, msg.Length - 1);
  4033. msg += "等文件保存失败!";
  4034. }
  4035. return Ok(JsonView(true, msg, new { id = dto.id, fileUrls = returnFileUrls }));
  4036. }
  4037. return Ok(JsonView(false, "操作失败!"));
  4038. }
  4039. /// <summary>
  4040. /// 删除文件(邮件截图)
  4041. /// </summary>
  4042. /// <param name="dto"></param>
  4043. /// <returns></returns>
  4044. [HttpPost]
  4045. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4046. public async Task<IActionResult> OfficialActivitiesDelFile(OfficialActivitiesDelFileDto dto)
  4047. {
  4048. string networkPath = AppSettingsHelper.Get("GrpFileBaseUrl");
  4049. string localPath = AppSettingsHelper.Get("GrpFileBasePath");
  4050. string ptfPath = AppSettingsHelper.Get("GrpFileFtpPath");
  4051. if (dto.Id < 1 || string.IsNullOrEmpty(dto.FileName))
  4052. {
  4053. return Ok(JsonView(false, "参数有误,上传失败!"));
  4054. }
  4055. string localFileDir = $"{localPath}{ptfPath}";
  4056. List<string> fileUrls = new List<string>();
  4057. var oaInfo = await _sqlSugar.Queryable<Res_OfficialActivities>().Where(x => x.Id == dto.Id).FirstAsync();
  4058. if (oaInfo != null)
  4059. {
  4060. string urlJson = oaInfo.ScreenshotOfMailUrl ?? "";
  4061. if (!string.IsNullOrEmpty(urlJson))
  4062. {
  4063. List<string> urls = JsonConvert.DeserializeObject<List<string>>(urlJson);
  4064. var filePath = urls.Find(x => x.Contains(dto.FileName));
  4065. if (string.IsNullOrEmpty(filePath)) return Ok(JsonView(false, "文件不存在!"));
  4066. var updFile = urls.Remove(filePath);
  4067. if (updFile)
  4068. {
  4069. //删除文件
  4070. string fileUrl = AppSettingsHelper.Get("GrpFileBasePath").Replace(@"/Office/GrpFile", "") + filePath;
  4071. if (System.IO.File.Exists(fileUrl))
  4072. {
  4073. System.IO.File.Delete(fileUrl);
  4074. }
  4075. string urlJsonstr = JsonConvert.SerializeObject(urls);
  4076. var upd = await _sqlSugar.Updateable<Res_OfficialActivities>()
  4077. .SetColumns(x => x.ScreenshotOfMailUrl == urlJsonstr)
  4078. .Where(x => x.Id == dto.Id)
  4079. .ExecuteCommandAsync();
  4080. if (upd > 0) return Ok(JsonView(true, "操作成功!"));
  4081. }
  4082. }
  4083. }
  4084. return Ok(JsonView(false, "操作失败!"));
  4085. }
  4086. /// <summary>
  4087. /// 公务出访 确认、取消邀请
  4088. /// </summary>
  4089. /// <param name="dto"></param>
  4090. /// <returns></returns>
  4091. [HttpPost]
  4092. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4093. public async Task<IActionResult> OfficialActivitiesInviteOperation(OfficialActivitiesInviteOperationDto dto)
  4094. {
  4095. if (dto.Id < 1) return Ok(JsonView(false, "Id参数有误!"));
  4096. if (dto.Type < 0 || dto.Type > 1) return Ok(JsonView(false, "Type参数有误!"));
  4097. var upd = await _sqlSugar.Updateable<Res_OfficialActivities>()
  4098. .SetColumns(x => x.ConfirmTheInvitation == dto.Type)
  4099. .Where(x => x.Id == dto.Id)
  4100. .ExecuteCommandAsync();
  4101. if (upd > 0) return Ok(JsonView(true, "操作成功!"));
  4102. return Ok(JsonView(false, "操作失败!"));
  4103. }
  4104. /// <summary>
  4105. /// 上传文件
  4106. /// </summary>
  4107. /// <param name="file"></param>
  4108. /// <returns></returns>
  4109. [HttpPost]
  4110. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4111. public async Task<IActionResult> UploadOfficialActivities(IFormFile file)
  4112. {
  4113. try
  4114. {
  4115. int Type = int.Parse(Request.Headers["Type"]);//1公务方简介,2公务活动图片,3发票
  4116. int DiId = int.Parse(Request.Headers["DiId"]);
  4117. int CreateUserId = int.Parse(Request.Headers["CreateUserId"]);
  4118. if (file != null)
  4119. {
  4120. var fileDir = AppSettingsHelper.Get("GrpFileBasePath");
  4121. //文件名称
  4122. string projectFileName = file.FileName;
  4123. //上传的文件的路径
  4124. string filePath = "";
  4125. if (!Directory.Exists(fileDir))
  4126. {
  4127. Directory.CreateDirectory(fileDir);
  4128. }
  4129. //上传的文件的路径
  4130. filePath = fileDir + $@"\商邀相关文件\{projectFileName}";
  4131. using (FileStream fs = System.IO.File.Create(filePath))
  4132. {
  4133. file.CopyTo(fs);
  4134. fs.Flush();
  4135. }
  4136. Grp_DeleFile d = new Grp_DeleFile();
  4137. d.Diid = DiId;
  4138. d.Category = 970;
  4139. if (Type == 1) d.Kind = 1;
  4140. else if (Type == 2) d.Kind = 2;
  4141. else if (Type == 3) d.Kind = 3;
  4142. d.FileName = projectFileName;
  4143. d.FilePath = "";
  4144. d.CreateUserId = CreateUserId;
  4145. int id = await _sqlSugar.Insertable(d).ExecuteReturnIdentityAsync();
  4146. return Ok(JsonView(true, "上传成功!", projectFileName));
  4147. }
  4148. else
  4149. {
  4150. return Ok(JsonView(false, "上传失败!"));
  4151. }
  4152. }
  4153. catch (Exception ex)
  4154. {
  4155. return Ok(JsonView(false, "程序错误!"));
  4156. throw;
  4157. }
  4158. }
  4159. /// <summary>
  4160. /// 删除文件
  4161. /// </summary>
  4162. /// <param name="dto"></param>
  4163. /// <returns></returns>
  4164. [HttpPost]
  4165. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4166. public async Task<IActionResult> DelloadOfficialActivities(DelBaseDto dto)
  4167. {
  4168. try
  4169. {
  4170. var fileDir = AppSettingsHelper.Get("GrpFileBasePath");
  4171. Grp_DeleFile _DeleFile = await _sqlSugar.Queryable<Grp_DeleFile>().FirstAsync(a => a.Id == dto.Id);
  4172. if (_DeleFile != null)
  4173. {
  4174. string fileName = _DeleFile.FileName;
  4175. string filePath = fileDir + "/团组增减款项相关文件/" + fileName;
  4176. // 删除该文件
  4177. System.IO.File.Delete(filePath);
  4178. int id = await _sqlSugar.Updateable<Grp_DeleFile>().Where(a => a.Id == dto.Id).SetColumns(a => new Grp_DeleFile { IsDel = 1, DeleteUserId = dto.DeleteUserId, DeleteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }).ExecuteCommandAsync();
  4179. return Ok(JsonView(true, "取消文件成功!"));
  4180. }
  4181. else
  4182. {
  4183. return Ok(JsonView(false, "取消文件失败!"));
  4184. }
  4185. }
  4186. catch (Exception ex)
  4187. {
  4188. return Ok(JsonView(false, "程序错误!"));
  4189. throw;
  4190. }
  4191. }
  4192. /// <summary>
  4193. /// 删除公务出访信息
  4194. /// </summary>
  4195. /// <param name="dto"></param>
  4196. /// <returns></returns>
  4197. [HttpPost]
  4198. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4199. public async Task<IActionResult> DelOfficialActivities(DelBaseDto dto)
  4200. {
  4201. _sqlSugar.BeginTran();
  4202. var res = await _officialActivitiesRep.SoftDeleteByIdAsync<Res_OfficialActivities>(dto.Id.ToString(), dto.DeleteUserId);
  4203. if (!res)
  4204. {
  4205. _sqlSugar.RollbackTran();
  4206. return Ok(JsonView(false, "删除失败"));
  4207. }
  4208. #region 删除公务出访
  4209. await _sqlSugar.Updateable<Grp_OfficialDutyLinkTranslator>()
  4210. .SetColumns(x => new Grp_OfficialDutyLinkTranslator()
  4211. {
  4212. DeleteUserId = dto.DeleteUserId,
  4213. DeleteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  4214. IsDel = 1,
  4215. Remark = $"公务出访-->删除"
  4216. })
  4217. .Where(x => x.OfficialDutyId == dto.Id)
  4218. .ExecuteCommandAsync();
  4219. #endregion
  4220. _sqlSugar.CommitTran();
  4221. return Ok(JsonView(true, "删除成功!"));
  4222. }
  4223. /// <summary>
  4224. /// 公务出访
  4225. /// 请示范例提示
  4226. /// Add Time:2024-05-13 13:56:44
  4227. /// </summary>
  4228. /// <param name="dto"></param>
  4229. /// <returns></returns>
  4230. [HttpPost]
  4231. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4232. public async Task<IActionResult> PostOfficialActivitiesReqReqSampleTips(PostOfficialActivitiesReqReqSampleTipsDto dto)
  4233. {
  4234. var res = await _officialActivitiesRep.PostReqReqSampleTips(dto.country, dto.area, dto.client);
  4235. if (res.Code == 0)
  4236. {
  4237. return Ok(JsonView(true, "操作成功!", res.Data));
  4238. }
  4239. return Ok(JsonView(false, res.Msg));
  4240. }
  4241. /// <summary>
  4242. /// 公务出访 (省外办,市外办) File Downlaod
  4243. /// </summary>
  4244. /// <param name="dto"></param>
  4245. /// <returns></returns>
  4246. [HttpPost]
  4247. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4248. public async Task<IActionResult> OfficialActivitiesFileDownload(OfficialActivitiesFileDownload dto)
  4249. {
  4250. #region 参数验证
  4251. if (dto.FileType < 1 || dto.FileType > 2) return Ok(JsonView(false, "请传入有效的FileType参数. 1 省外办出访请示 2 市外办出访请示", ""));
  4252. if (dto.DiId < 1) return Ok(JsonView(false, "请传入有效的DiId参数.", ""));
  4253. #endregion
  4254. //团组基础信息
  4255. var groupInfo = _sqlSugar.Queryable<Grp_DelegationInfo>().Where(it => it.IsDel == 0 && it.Id == dto.DiId).First();
  4256. if (groupInfo == null) return Ok(JsonView(false, "该团组基本信息不存在", ""));
  4257. groupInfo.VisitCountry = groupInfo.VisitCountry.Replace("|", "、");
  4258. //团组公务信息
  4259. var obDatas = _sqlSugar.Queryable<Res_OfficialActivities>().Where(it => it.IsDel == 0 && it.DiId == dto.DiId).OrderBy(it => it.Date).ToList();
  4260. //if (obDatas.Count < 1) return Ok(JsonView(false, "请先录入公务信息!"));
  4261. //团组客户名单
  4262. var guestResult = _tourClientListRep._ItemByDiId(1, dto.DiId);
  4263. List<TourClientListByDiIdView> guestInfos = new List<TourClientListByDiIdView>();
  4264. if (guestResult.Result.Code == 0) guestInfos = guestResult.Result.Data as List<TourClientListByDiIdView>;
  4265. string visitCountrys = ""; //××国家(或地区)×天,××国家(或地区)×天
  4266. string countryStayStr = ""; // xx、xx、xx
  4267. //出入境费用 住宿类型
  4268. var dayCostDatas = _sqlSugar.Queryable<Grp_DayAndCost>().Where(it => it.IsDel == 0 && it.DiId == dto.DiId && it.Type == 1).ToList();
  4269. if (dayCostDatas.Count > 0)
  4270. {
  4271. List<int> nationalIds = dayCostDatas.Select(it => it.NationalTravelFeeId).ToList();
  4272. var nationalDatas = _sqlSugar.Queryable<Grp_NationalTravelFee>().Where(it => nationalIds.Contains(it.Id)).ToList();
  4273. var nationalDataGroupByCountry = nationalDatas.GroupBy(it => it.Country);
  4274. foreach (var item in nationalDataGroupByCountry)
  4275. {
  4276. visitCountrys += $"{item.Key}、";
  4277. int stayDays = nationalIds.Where(it => it == item.ToList()[0].Id).Count();
  4278. countryStayStr += $"{item.Key}{stayDays}天,";
  4279. }
  4280. if (visitCountrys.Length > 0) visitCountrys = visitCountrys.Substring(0, visitCountrys.Length - 1);
  4281. if (countryStayStr.Length > 0) countryStayStr = countryStayStr.Substring(0, countryStayStr.Length - 1);
  4282. }
  4283. else
  4284. {
  4285. visitCountrys = groupInfo.VisitCountry;
  4286. countryStayStr = GeneralMethod.GetCountryStandingTime(groupInfo.Id); //计算国家出访天数
  4287. }
  4288. //出访人数
  4289. int visitPeopleNum = groupInfo.VisitPNumber;
  4290. int visitDaysNum = groupInfo.VisitDays;
  4291. //出访单位
  4292. string obInfoStr = "";
  4293. foreach (var ob in obDatas) obInfoStr += @$"{ob.Client.Trim()}{ob.Job.Trim()}{ob.Contact.Trim()}、";
  4294. if (obInfoStr.Length > 0) obInfoStr = obInfoStr.Substring(0, obInfoStr.Length - 1);
  4295. obInfoStr = obInfoStr ?? "[公务出访未录入]";
  4296. //出访路线
  4297. string lineStr = GeneralMethod.GetGroupCityLine(groupInfo.Id, "—");
  4298. if (dto.FileType == 1)
  4299. {
  4300. //载入模板
  4301. string tempPath = AppSettingsHelper.Get("WordBasePath") + "Template/省外办出访请示 - 模板.docx";
  4302. var doc = new Document(tempPath);
  4303. DocumentBuilder builder = new DocumentBuilder(doc);
  4304. //键值对存放数据
  4305. Dictionary<string, string> dic = new Dictionary<string, string>();
  4306. //××(组团单位):接团客户信息团组
  4307. dic.Add("GroupClient", $"{groupInfo.ClientUnit}\r\n");
  4308. //关于××(职务、姓名)等×人赴××(国家或地区)进行×××(出访目的)的请示
  4309. string guestName = "";
  4310. string guestJob = "";
  4311. string guestInfoStr = "";
  4312. var guestFirstInfo = guestInfos.FirstOrDefault();
  4313. if (guestFirstInfo != null)
  4314. {
  4315. guestName = guestFirstInfo.LastName.Trim() + guestFirstInfo.FirstName.Trim();
  4316. guestJob = guestFirstInfo.Job.Trim();
  4317. guestInfoStr = $@"{guestJob}、{guestName}";
  4318. }
  4319. guestInfoStr = guestInfoStr ?? "[接团客户名单未录入]";
  4320. string askTitle = $@"关于{guestInfoStr}等{visitPeopleNum}人赴{visitCountrys}进行{groupInfo.VisitPurpose}的请示";
  4321. dic.Add("AskTitle", askTitle);
  4322. //应×××(邀请方名称+邀请人职务和姓名)的邀请,我单位拟派×××(职务、姓名)等×人(人数)于×××年×××月×××日赴×××(国家或地区)进行×××(出访目的)。现请示如下。
  4323. string visitDateStr = @$"{groupInfo.VisitDate.Year}年{groupInfo.VisitDate.Month}月{groupInfo.VisitDate.Day}日";
  4324. string askSubTitle = $@"应{obInfoStr}的邀请,我单位拟派{guestInfoStr}等{visitPeopleNum}人于{visitDateStr}赴{visitCountrys}进行{groupInfo.VisitPurpose}。现请示如下。";
  4325. dic.Add("AskSubTitle", askSubTitle);
  4326. //出访目的
  4327. dic.Add("VisitPurpose", groupInfo.VisitPurpose);
  4328. //出访任务
  4329. //(一)××(国家或地区)
  4330. //1.拜访×××(机构名称)×××(姓名、职务)洽谈(或调研、推动等)×××(项目或机构名称等)。(例:拜会×××经济与发展司司长×××,商讨“×××活动”相关筹备工作。)
  4331. //2.拜访×××(机构名称)×××(姓名、职务)洽谈(或调研、推动等)×××(项目或机构名称等)。(例:拜会×××经济与发展司司长×××,商讨“×××活动”相关筹备工作。)
  4332. string obBackgroundStr = "";//出访背景
  4333. string taskStr = ""; ; //出访任务
  4334. var countrys = obDatas.GroupBy(it => it.Country);
  4335. int countryIndex = 1;
  4336. foreach (var item in countrys)
  4337. {
  4338. string taskTitle = $"({GetToUpperNumber(countryIndex)}){item.Key}\r\n";
  4339. string taskContent = "";
  4340. string obBackgroundContent = "";
  4341. int obIndex = 1;
  4342. foreach (var obInfo in item.ToList())
  4343. {
  4344. string reqSmaple = "";
  4345. string settingStr = "";
  4346. if (!string.IsNullOrEmpty(obInfo.ReqSample)) reqSmaple = obInfo.ReqSample;
  4347. else reqSmaple = "[公务出访请示范例未录入]";
  4348. if (!string.IsNullOrEmpty(obInfo.Setting)) settingStr = obInfo.Setting;
  4349. else settingStr = "[公务方背景未录入]";
  4350. taskContent += $"{obIndex}. {reqSmaple}\r\n";
  4351. obBackgroundContent += $"{obIndex}. {obInfo.Client}:{settingStr}\r\n";
  4352. obIndex++;
  4353. }
  4354. taskStr += $"{taskTitle}{taskContent}";
  4355. obBackgroundStr += $"{taskTitle}{obBackgroundContent}";
  4356. countryIndex++;
  4357. }
  4358. //出访背景
  4359. if (obBackgroundStr.Length < 1) obBackgroundStr = "[公务出访背景未录入]";
  4360. dic.Add("OBSetting", obBackgroundStr);
  4361. //出访任务
  4362. if (taskStr.Length < 1) taskStr = "[公务出访任务未录入]";
  4363. dic.Add("TaskContent", taskStr);
  4364. //出访时间
  4365. //代表团拟于××年×月×日—×月×日出访,在外停留×天。其中,××国家(或地区)×天,××国家(或地区)×天。
  4366. string visitTimeQuantumStr = $"代表团拟于{groupInfo.VisitStartDate.Year}年{groupInfo.VisitStartDate.Month}月{groupInfo.VisitStartDate.Day}日—{groupInfo.VisitEndDate.Month}月{groupInfo.VisitEndDate.Day}日出访,在外停留{visitDaysNum}天。其中,{countryStayStr}。";
  4367. //出访时间
  4368. dic.Add("TimeQuantum", visitTimeQuantumStr);
  4369. //出访路线
  4370. //成都—××(出境城市名称)—××(转机不出机场)—××(公务所在城市)……—××(入境城市名称)—成都。(例:成都—法兰克福<转机不出机场>—巴黎—巴塞罗那—阿姆斯特丹<转机不出机场>-成都)
  4371. dic.Add("Line", lineStr);
  4372. //scheduling //行程安排
  4373. string schedulingStr = $"[OP行程单暂未生成]";
  4374. #region op行程 根据黑屏代码录入
  4375. var opTripView = GeneralMethod.GetBriefStroke(groupInfo.Id);
  4376. if (opTripView.Code != 0) schedulingStr = $"[{opTripView.Msg}]";
  4377. schedulingStr = "";
  4378. List<Grp_TravelList> travelList = new List<Grp_TravelList>();
  4379. travelList = opTripView.Data as List<Grp_TravelList>;
  4380. if (travelList != null)
  4381. {
  4382. foreach (var item in travelList)
  4383. {
  4384. schedulingStr += $"{item.Date}({item.WeekDay})\r\n{item.Trip}\r\n";
  4385. }
  4386. }
  4387. #endregion
  4388. dic.Add("Scheduling", schedulingStr);
  4389. #region 填充word模板书签内容
  4390. foreach (var key in dic.Keys)
  4391. {
  4392. builder.MoveToBookmark(key);
  4393. builder.Write(dic[key]);
  4394. }
  4395. #endregion
  4396. //获取word里所有表格
  4397. NodeCollection allTables = doc.GetChildNodes(NodeType.Table, true);
  4398. //获取所填表格的序数
  4399. Aspose.Words.Tables.Table tableOne = allTables[0] as Aspose.Words.Tables.Table;
  4400. var rowStart = tableOne.Rows[0]; //获取第1行
  4401. //循环赋值
  4402. for (int i = 0; i < guestInfos.Count; i++)
  4403. {
  4404. var guestInfo = guestInfos[i];
  4405. builder.MoveToCell(0, i + 1, 0, 0);
  4406. builder.Write(guestInfo.LastName + guestInfo.FirstName);
  4407. builder.MoveToCell(0, i + 1, 1, 0);
  4408. int sex = guestInfo.Sex;
  4409. string sexStr = string.Empty;
  4410. if (sex == 0) sexStr = "男";
  4411. else if (sex == 1) sexStr = "女";
  4412. else sexStr = "-";
  4413. builder.Write(sexStr);
  4414. builder.MoveToCell(0, i + 1, 2, 0);
  4415. builder.Write(guestInfo.CompanyFullName + guestInfo.Job);
  4416. builder.MoveToCell(0, i + 1, 3, 0);
  4417. //string birthDay = "";
  4418. string birthDayStr = string.Empty;
  4419. if (guestInfo.BirthDay != DateTime.MinValue)
  4420. {
  4421. birthDayStr = guestInfo.BirthDay.ToString("yyyy.MM");
  4422. }
  4423. builder.Write(birthDayStr);
  4424. }
  4425. //删除多余行
  4426. while (tableOne.Rows.Count > guestInfos.Count + 1)
  4427. {
  4428. tableOne.Rows.RemoveAt(guestInfos.Count + 1);
  4429. }
  4430. var fileDir = AppSettingsHelper.Get("WordBasePath");
  4431. string fileName = $"{groupInfo.TeamName}省外办出访请示{DateTime.Now.ToString("yyyyMMddHHmmss")}.docx";
  4432. string filePath = fileDir + $@"OfficialActivities/{fileName}";
  4433. doc.Save(filePath);
  4434. string Url = $@"{AppSettingsHelper.Get("WordBaseUrl")}Office/Word/OfficialActivities/{fileName}";
  4435. return Ok(JsonView(true, "操作成功!", Url));
  4436. }
  4437. else if (dto.FileType == 2)
  4438. {
  4439. //载入模板
  4440. string tempPath = AppSettingsHelper.Get("WordBasePath") + "Template/市外办出访请示 - 模板.docx";
  4441. var doc = new Document(tempPath);
  4442. DocumentBuilder builder = new DocumentBuilder(doc);
  4443. //键值对存放数据
  4444. var dic = new Dictionary<string, string>
  4445. {
  4446. //××(组团单位):接团客户信息团组
  4447. { "GroupClient", $"{groupInfo.ClientUnit}" },
  4448. { "GroupClient1", $"{groupInfo.ClientUnit}" }
  4449. };
  4450. //关于××(职务、姓名)等×人赴××(国家或地区)进行×××(出访目的)的请示
  4451. string guestName = "";
  4452. string guestJob = "";
  4453. string guestInfoStr = "";
  4454. var guestFirstInfo = guestInfos.FirstOrDefault();
  4455. if (guestFirstInfo != null)
  4456. {
  4457. guestName = guestFirstInfo.LastName.Trim() + guestFirstInfo.FirstName.Trim();
  4458. guestJob = guestFirstInfo.Job;
  4459. guestInfoStr = $@"{guestJob}、{guestName.Trim()}";
  4460. }
  4461. string reqTitle = $@"关于{guestInfoStr}等{visitPeopleNum}人赴{visitCountrys}进行{groupInfo.VisitPurpose}的请示";
  4462. dic.Add("ReqTitle", reqTitle);
  4463. //应×××(邀请方名称+邀请人职务和姓名)的邀请,我单位拟派×××(职务、姓名)等×人(人数)于×××年×××月×××日赴×××(国家或地区)进行×××(出访目的)。
  4464. string visitDateStr = @$"{groupInfo.VisitDate.Year}年{groupInfo.VisitDate.Month}月{groupInfo.VisitDate.Day}日";
  4465. string reqSubTitle = $@"应{obInfoStr}的邀请,我单位拟派{guestInfoStr}等{visitPeopleNum}人于{visitDateStr}赴{visitCountrys}进行{groupInfo.VisitPurpose}。";
  4466. dic.Add("ReqSubTitle", reqSubTitle);
  4467. /*
  4468. * 出访任务
  4469. * (一)××(国家或地区)
  4470. * 1.拜访×××(机构名称)×××(姓名、职务)洽谈(或调研、推动等)×××(项目或机构名称等)。(例:拜会×××经济与发展司司长×××,商讨“×××活动”相关筹备工作。)背景:拟拜访机构的优势、拟洽谈项目的前期进展情况等。(例:背景:由×××总领馆联合×××市政府共同举办的“×××活动”将于今年6月在×××举行。)
  4471. * 2.拜访×××(机构名称)×××(姓名、职务)洽谈(或调研等)×××(项目或机构名称等)。(例:拜会友城×××市市长×××,巩固和发展两市传统友谊,商谈两市未来互动交流合作项目。)背景:拟拜访机构的优势、拟洽谈项目的前期进展情况等。(例:背景:×××年×月,×××市与×××市正式缔结友好城市关系。在此框架下,两市开展了一系列友好互访和商务交流。并于×××年×月共同举办了“×××活动”。)
  4472. *
  4473. */
  4474. string taskStr = string.Empty;
  4475. List<string> countrys = obDatas.Where(it => !string.IsNullOrEmpty(it.Country)).Select(it => it.Country).ToList();
  4476. int countryIndex = 1;
  4477. foreach (var item in countrys)
  4478. {
  4479. string taskTitle = $"({GetToUpperNumber(countryIndex)}){item ?? "[公务出访国家未填写]"}\r\n";
  4480. string taskContent = "";
  4481. if (!string.IsNullOrEmpty(item))
  4482. {
  4483. var countryObDatas = obDatas.Where(it => !string.IsNullOrEmpty(it.Country) && it.Country.Contains(item)).OrderBy(it => it.Date).ToList();
  4484. int obIndex = 1;
  4485. if (countryObDatas.Count == 0) taskContent = "[公务出访未录入]\r\n";
  4486. else
  4487. {
  4488. foreach (var obInfo in countryObDatas)
  4489. {
  4490. taskContent += $"{obIndex}.{obInfo.ReqSample ?? "[公务出访请示范例未填写]"}\r\n背景:{obInfo.Setting ?? "[公务出访背景未填写]"}\r\n";
  4491. obIndex++;
  4492. }
  4493. }
  4494. }
  4495. taskStr += $"{taskTitle}{taskContent}";
  4496. countryIndex++;
  4497. }
  4498. if (string.IsNullOrEmpty(taskStr)) taskStr = "××××××";
  4499. //出访任务
  4500. dic.Add("TaskContent", taskStr);
  4501. //出访目的
  4502. dic.Add("VisitPurpose", groupInfo.VisitPurpose);
  4503. //出访信息
  4504. //代表团拟于××年×月×日—×月×日出访,在外停留×天。其中,××国家(或地区)×天,××国家(或地区)×天。出访路线:成都—××(出境城市名称)—××(转机不出机场)—××(公务所在城市)……—××(入境城市名称)—成都。(例:成都—法兰克福<转机不出机场>—巴黎—巴塞罗那—阿姆斯特丹<转机不出机场>-成都)出访费用:由××承担(注明由外方或上级机关承担,还是由派员单位在年度安排的预算经费中列支)。
  4505. string tripInfoStr = "";
  4506. tripInfoStr = $"代表团拟于{groupInfo.VisitStartDate.Year}年{groupInfo.VisitStartDate.Month}月{groupInfo.VisitStartDate.Day}日—{groupInfo.VisitEndDate.Month}月{groupInfo.VisitEndDate.Day}日出访,在外停留{visitDaysNum}天。其中,{countryStayStr}。出访路线:{lineStr}。出访费用:由××承担(注明由外方或上级机关承担,还是由派员单位在年度安排的预算经费中列支)";
  4507. dic.Add("TripInfo", tripInfoStr);
  4508. #region 填充word模板书签内容
  4509. foreach (var key in dic.Keys)
  4510. {
  4511. builder.MoveToBookmark(key);
  4512. builder.Write(dic[key]);
  4513. }
  4514. #endregion
  4515. //获取word里所有表格
  4516. NodeCollection allTables = doc.GetChildNodes(NodeType.Table, true);
  4517. //获取所填表格的序数
  4518. Aspose.Words.Tables.Table tableOne = allTables[0] as Aspose.Words.Tables.Table;
  4519. var rowStart = tableOne.Rows[0]; //获取第1行
  4520. //循环赋值
  4521. for (int i = 0; i < guestInfos.Count; i++)
  4522. {
  4523. var guestInfo = guestInfos[i];
  4524. builder.MoveToCell(0, i + 1, 0, 0);
  4525. builder.Write(guestInfo.LastName + guestInfo.FirstName);
  4526. builder.MoveToCell(0, i + 1, 1, 0);
  4527. int sex = guestInfo.Sex;
  4528. string sexStr = string.Empty;
  4529. if (sex == 0) sexStr = "男";
  4530. else if (sex == 1) sexStr = "女";
  4531. else sexStr = "未设置";
  4532. builder.Write(sexStr);
  4533. builder.MoveToCell(0, i + 1, 2, 0);
  4534. builder.Write(guestInfo.CompanyFullName + guestInfo.Job);
  4535. builder.MoveToCell(0, i + 1, 3, 0);
  4536. DateTime birthDay = guestInfo.BirthDay;
  4537. string birthDayStr = string.Empty;
  4538. if (birthDay != DateTime.MinValue)
  4539. {
  4540. birthDayStr = birthDay.ToString("yyyy.MM");
  4541. }
  4542. builder.Write(birthDayStr);
  4543. }
  4544. //删除多余行
  4545. while (tableOne.Rows.Count > guestInfos.Count + 1)
  4546. {
  4547. tableOne.Rows.RemoveAt(guestInfos.Count + 1);
  4548. }
  4549. var fileDir = AppSettingsHelper.Get("WordBasePath");
  4550. var fileName = $"{groupInfo.TeamName}市外办出访请示{DateTime.Now:yyyyMMddHHmmss}.docx";
  4551. var filePath = fileDir + $@"OfficialActivities/{fileName}";
  4552. doc.Save(filePath);
  4553. var url = $@"{AppSettingsHelper.Get("WordBaseUrl")}Office/Word/OfficialActivities/{fileName}";
  4554. return Ok(JsonView(true, "操作成功!", url));
  4555. }
  4556. return Ok(JsonView(true, "操作失败!", ""));
  4557. }
  4558. private static string GetToUpperNumber(int num)
  4559. {
  4560. string numStr = "";
  4561. if (num == 1) numStr = "一";
  4562. else if (num == 2) numStr = "二";
  4563. else if (num == 3) numStr = "三";
  4564. else if (num == 4) numStr = "四";
  4565. else if (num == 5) numStr = "五";
  4566. else if (num == 6) numStr = "六";
  4567. else if (num == 7) numStr = "七";
  4568. else if (num == 8) numStr = "八";
  4569. else if (num == 9) numStr = "九";
  4570. else if (num == 10) numStr = "十";
  4571. return numStr;
  4572. }
  4573. [HttpPost]
  4574. public IActionResult ExportOfficialActivitiesInfo(ExportOfficialActivitiesInfoDto dto)
  4575. {
  4576. var jw = JsonView(false);
  4577. if (!ModelState.IsValid)
  4578. {
  4579. jw.Data = ModelState;
  4580. return Ok(jw);
  4581. }
  4582. var startTime_bool = DateTime.TryParse(dto.StartTime, out DateTime startTime_parse);
  4583. var endTime_bool = DateTime.TryParse(dto.EndTime, out DateTime endTime_parse);
  4584. if (startTime_parse > endTime_parse)
  4585. {
  4586. jw.Msg = "开始实际不能大于结束时间!";
  4587. return Ok(jw);
  4588. }
  4589. if (startTime_bool && endTime_bool)
  4590. {
  4591. //处理时间模板
  4592. var Query_DB = _sqlSugar.Queryable<Grp_DelegationInfo>()
  4593. .LeftJoin<Res_OfficialActivities>((a, b) => a.Id == b.DiId && b.IsDel == 0)
  4594. .LeftJoin<Sys_Users>((a, b, c) => b.CreateUserId == c.Id && c.IsDel == 0)
  4595. .Where((a, b, c) => a.IsDel == 0 && a.VisitDate >= startTime_parse && a.VisitDate <= endTime_parse)
  4596. .WhereIF(dto.State != -1, (a, b, c) => b.ConfirmTheInvitation == dto.State)
  4597. .Select((a, b, c) => new
  4598. {
  4599. a.TeamName,
  4600. b.Client,
  4601. b.ConfirmTheInvitation,
  4602. b.Contact,
  4603. ConfirmTheInvitationStr = b.ConfirmTheInvitation == 1 ? "是" : "否",
  4604. b.Date,
  4605. b.Nature,
  4606. c.CnName,
  4607. b.Address,
  4608. b.CreateTime
  4609. })
  4610. .ToList()
  4611. .Where(x => !string.IsNullOrWhiteSpace(x.Client))
  4612. .ToList();
  4613. if (Query_DB.Count > 0)
  4614. {
  4615. //打开excel
  4616. var ftpPath = AppSettingsHelper.Get("ExcelFtpPath");
  4617. var fileBasePath = AppSettingsHelper.Get("ExcelBasePath");
  4618. //var fileName = "公务出访信息.docx";
  4619. //创建数据源Table
  4620. DataTable dtSource = new DataTable();
  4621. dtSource.TableName = "TB";
  4622. var firstElem = Query_DB.First();
  4623. //遍历firstElem所有属性
  4624. foreach (var item in firstElem.GetType().GetProperties())
  4625. {
  4626. dtSource.Columns.Add(item.Name, item.PropertyType);
  4627. }
  4628. foreach (var item in Query_DB)
  4629. {
  4630. DataRow dr = dtSource.NewRow();
  4631. //遍历dtSource所有列头
  4632. foreach (DataColumn column in dtSource.Columns)
  4633. {
  4634. dr[column.ColumnName] = item.GetType().GetProperty(column.ColumnName)?.GetValue(item)?.ToString();
  4635. }
  4636. dtSource.Rows.Add(dr);
  4637. }
  4638. WorkbookDesigner designer = new WorkbookDesigner();
  4639. designer.Workbook = new Workbook(fileBasePath + ("Template/公务出访信息.xlsx"));
  4640. var title = startTime_parse.ToString("yyyy年MM月dd日") + " - " + endTime_parse.ToString("yyyy年MM月dd日") + " 公务出访信息";
  4641. designer.SetDataSource("title", title);
  4642. designer.SetDataSource(dtSource);
  4643. designer.Process();
  4644. var exportSerevePath = fileBasePath + "ExportOfficialActivitiesInfo/" + title + ".xlsx";
  4645. var exportFtpPaht = ftpPath + "ExportOfficialActivitiesInfo/" + title + ".xlsx";
  4646. //保存文件
  4647. designer.Workbook.Save(exportSerevePath);
  4648. jw.Data = AppSettingsHelper.Get("ExcelBaseUrl") + exportFtpPaht;
  4649. jw.Code = 200;
  4650. jw.Msg = "获取成功!";
  4651. }
  4652. else
  4653. {
  4654. jw.Data = "无公务信息!";
  4655. }
  4656. }
  4657. else
  4658. {
  4659. jw.Data = "时间格式错误!";
  4660. }
  4661. return Ok(jw);
  4662. }
  4663. #endregion
  4664. #region 请示数据库
  4665. /// <summary>
  4666. /// 查询请示数据库初始化
  4667. /// </summary>
  4668. /// <param name="dto"></param>
  4669. /// <returns></returns>
  4670. [HttpPost]
  4671. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4672. public async Task<IActionResult> QueryAskData(QueryAskDataDto dto)
  4673. {
  4674. Result groupData = await _askDataRep.QueryAskData(dto);
  4675. if (groupData.Code != 0)
  4676. {
  4677. return Ok(JsonView(false, groupData.Msg));
  4678. }
  4679. return Ok(JsonView(true, groupData.Msg, groupData.Data));
  4680. }
  4681. /// <summary>
  4682. /// 根据Id查询请示数据库单条数据
  4683. /// </summary>
  4684. /// <param name="dto"></param>
  4685. /// <returns></returns>
  4686. [HttpPost]
  4687. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4688. public async Task<IActionResult> QueryAskDataById(QueryAskDataByIdDto dto)
  4689. {
  4690. Res_AskData _AskData = await _sqlSugar.Queryable<Res_AskData>().FirstAsync(a => a.IsDel == 0 && a.Id == dto.id);
  4691. if (_AskData == null)
  4692. {
  4693. return Ok(JsonView(true, "暂无数据!", _AskData));
  4694. }
  4695. return Ok(JsonView(true, "查询成功!", _AskData));
  4696. }
  4697. /// <summary>
  4698. /// 请示数据库操作(Status:1.新增,2.修改)
  4699. /// </summary>
  4700. /// <param name="dto"></param>
  4701. /// <returns></returns>
  4702. [HttpPost]
  4703. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4704. public async Task<IActionResult> OpAskData(OpAskDataDto dto)
  4705. {
  4706. Result groupData = await _askDataRep.OpAskData(dto);
  4707. if (groupData.Code != 0)
  4708. {
  4709. return Ok(JsonView(false, groupData.Msg));
  4710. }
  4711. return Ok(JsonView(true, groupData.Msg, groupData.Data));
  4712. }
  4713. /// <summary>
  4714. /// 删除请示资料信息
  4715. /// </summary>
  4716. /// <param name="dto"></param>
  4717. /// <returns></returns>
  4718. [HttpPost]
  4719. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4720. public async Task<IActionResult> DelAskData(DelBaseDto dto)
  4721. {
  4722. var res = await _askDataRep.SoftDeleteByIdAsync<Res_AskData>(dto.Id.ToString(), dto.DeleteUserId);
  4723. if (!res)
  4724. {
  4725. return Ok(JsonView(false, "删除失败"));
  4726. }
  4727. return Ok(JsonView(true, "删除成功!"));
  4728. }
  4729. /// <summary>
  4730. /// 请示资料信息
  4731. /// 省外办下载
  4732. /// </summary>
  4733. /// <param name="dto"></param>
  4734. /// <returns></returns>
  4735. [HttpPost]
  4736. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  4737. public async Task<IActionResult> AskDataProvinceFAOPFile(AskDataProvinceFileDto dto)
  4738. {
  4739. if (dto.DataIdItem.Length < 1) return Ok(JsonView(false, $"请传入有效的数据Id集合!"));
  4740. if (dto.DiId < 1) return Ok(JsonView(false, $"请传入有效的数据DiId参数!"));
  4741. //大写数字序号
  4742. string[] num = { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十" ,
  4743. "十一","十二","十三","十四","十五","十六","十七","十八","十九","二十",
  4744. "二十一","二十二","二十三","二十四","二十五","二十六","二十七","二十八","二十九","三十",
  4745. "三十一","三十二","三十三","三十四","三十五","三十六","三十七","三十八","三十九","四十"};
  4746. //数据源
  4747. var idItem = dto.DataIdItem.OrderBy(x => x);
  4748. var askDatas = await _sqlSugar.Queryable<Res_AskData>().Where(x => x.IsDel == 0 && idItem.Contains(x.Id)).ToListAsync();
  4749. //书签名
  4750. string Area = "",
  4751. Official = "";
  4752. //表格数据源
  4753. DataTable dt = new DataTable();
  4754. dt.Columns.Add("Country", typeof(string));
  4755. dt.Columns.Add("TalkCase", typeof(string));
  4756. int id = 0;
  4757. int TalkcaseOrder = 0;
  4758. int RowOrder = 0;
  4759. //填充数据
  4760. for (int i = 0; i < askDatas.Count; i++)
  4761. {
  4762. var ad = askDatas[i];
  4763. Area = Area + ad.Country + ad.Area + "、";
  4764. Official = Official + ad.UnitName + "、";
  4765. //填充表格数据源
  4766. DataRow dr = dt.NewRow();
  4767. if (i > 0)
  4768. {
  4769. var adtemp = askDatas[i - 1];
  4770. if (ad.Country == adtemp.Country)
  4771. {
  4772. TalkcaseOrder++;
  4773. dt.Rows[RowOrder]["TalkCase"] = dt.Rows[RowOrder]["TalkCase"] + "\r\n" + (1 + TalkcaseOrder).ToString() + "、" + ad.TalkCase;
  4774. }
  4775. else
  4776. {
  4777. RowOrder++;
  4778. dr = dt.NewRow();
  4779. dr["Country"] = "(" + num[RowOrder] + ")" + ad.Country;
  4780. dr["TalkCase"] = "1、" + ad.TalkCase;
  4781. dt.Rows.Add(dr);
  4782. TalkcaseOrder = 0;
  4783. }
  4784. }
  4785. else
  4786. {
  4787. dr["Country"] = "(" + num[i] + ")" + ad.Country;
  4788. dr["TalkCase"] = "1、" + ad.TalkCase;
  4789. dt.Rows.Add(dr);
  4790. }
  4791. id = ad.Id;
  4792. }
  4793. //模板路径
  4794. var tempPath = AppSettingsHelper.Get("WordBasePath") + "Template/省外办出访请示模板.doc";
  4795. //载入模板
  4796. Aspose.Words.Document doc = new Aspose.Words.Document(tempPath);
  4797. #region 填充word内容
  4798. #region 填充请示内容
  4799. //利用DocumentBuilder处理表格或是书签
  4800. Aspose.Words.DocumentBuilder builder = new DocumentBuilder(doc);
  4801. string bookmark = "";
  4802. try
  4803. {
  4804. for (int i = 0; i < dt.Rows.Count; i++)
  4805. {
  4806. bookmark = bookmark
  4807. + dt.Rows[i]["Country"].ToString() + "\r\n"
  4808. + dt.Rows[i]["TalkCase"].ToString() + "\r\n";
  4809. }
  4810. }
  4811. catch
  4812. {
  4813. }
  4814. #endregion
  4815. #region 填充word模板书签内容
  4816. //团组信息
  4817. var di = await _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && x.Id == dto.DiId).FirstAsync();
  4818. //接团客户名单实例
  4819. string client_sql = string.Format(@"
  4820. SELECT
  4821. tcl.Id,
  4822. tcl.DiId,
  4823. tcl.IsAccompany,
  4824. temp.*,
  4825. u.CnName AS Operator,
  4826. tcl.CreateTime AS OperatingTime
  4827. FROM
  4828. Grp_TourClientList tcl
  4829. LEFT JOIN (
  4830. SELECT
  4831. dc.Id AS DcId,
  4832. dc.LastName,
  4833. dc.FirstName,
  4834. ccom.CompanyFullName,
  4835. dc.Job,
  4836. cc.CertNo AS IDCardNo,
  4837. dc.Sex,
  4838. dc.BirthDay
  4839. FROM
  4840. Crm_DeleClient dc
  4841. LEFT JOIN Crm_CustomerCompany ccom ON dc.CrmCompanyId = ccom.Id
  4842. AND ccom.IsDel = 0
  4843. LEFT JOIN Crm_CustomerCert cc ON dc.Id = cc.DcId
  4844. AND cc.SdId = 773
  4845. AND cc.IsDel = 0
  4846. WHERE
  4847. dc.IsDel = 0
  4848. ) temp ON temp.DcId = tcl.ClientId
  4849. LEFT JOIN Sys_Users u ON tcl.CreateUserId = u.Id
  4850. WHERE
  4851. tcl.IsDel = 0
  4852. AND tcl.DiId = {0}", dto.DiId);
  4853. var clientList = await _sqlSugar.SqlQueryable<TourClientListDetailsView>(client_sql).ToListAsync();
  4854. //机票代码实例
  4855. DataTable airTable = GeneralMethod.GetTableByBlackCode(dto.DiId);
  4856. //三字码
  4857. var threeCodes = await _sqlSugar.Queryable<Res_ThreeCode>().Where(x => x.IsDel == 0).ToListAsync();
  4858. //团名
  4859. if (doc.Range.Bookmarks["TeamName"] != null)
  4860. {
  4861. Bookmark mark = doc.Range.Bookmarks["TeamName"];
  4862. mark.Text = di.TeamName;
  4863. }
  4864. //团长名
  4865. if (doc.Range.Bookmarks["ClientName2"] != null)
  4866. {
  4867. Bookmark mark = doc.Range.Bookmarks["ClientName2"];
  4868. if (clientList == null || clientList.Count == 0)
  4869. {
  4870. mark.Text = "【本团尚未录入客户名单,请联系主管!】";
  4871. }
  4872. else
  4873. {
  4874. mark.Text = clientList[0].CompanyFullName + clientList[0].Job + clientList[0].LastName + clientList[0].FirstName;
  4875. }
  4876. }
  4877. if (doc.Range.Bookmarks["ClientName"] != null)
  4878. {
  4879. Bookmark mark = doc.Range.Bookmarks["ClientName"];
  4880. if (clientList == null || clientList.Count == 0)
  4881. {
  4882. mark.Text = "【本团尚未录入客户名单,请联系主管!】";
  4883. }
  4884. else
  4885. {
  4886. mark.Text = clientList[0].CompanyFullName + clientList[0].Job + clientList[0].LastName + clientList[0].FirstName;
  4887. }
  4888. }
  4889. //跟团人数
  4890. if (doc.Range.Bookmarks["ClientNumber2"] != null)
  4891. {
  4892. Bookmark mark = doc.Range.Bookmarks["ClientNumber2"];
  4893. mark.Text = di.VisitPNumber.ToString();
  4894. }
  4895. if (doc.Range.Bookmarks["ClientNumber"] != null)
  4896. {
  4897. Bookmark mark = doc.Range.Bookmarks["ClientNumber"];
  4898. mark.Text = di.VisitPNumber.ToString();
  4899. }
  4900. //地区
  4901. if (doc.Range.Bookmarks["Area"] != null)
  4902. {
  4903. Bookmark mark = doc.Range.Bookmarks["Area"];
  4904. mark.Text = Area.TrimEnd('、');
  4905. }
  4906. if (doc.Range.Bookmarks["Area2"] != null)
  4907. {
  4908. Bookmark mark = doc.Range.Bookmarks["Area2"];
  4909. mark.Text = Area.TrimEnd('、');
  4910. }
  4911. //出访目的
  4912. if (doc.Range.Bookmarks["Destination2"] != null)
  4913. {
  4914. Bookmark mark = doc.Range.Bookmarks["Destination2"];
  4915. mark.Text = di.VisitPurpose;
  4916. }
  4917. if (doc.Range.Bookmarks["Destination"] != null)
  4918. {
  4919. Bookmark mark = doc.Range.Bookmarks["Destination"];
  4920. mark.Text = di.VisitPurpose;
  4921. }
  4922. //邀请方
  4923. if (doc.Range.Bookmarks["Official"] != null)
  4924. {
  4925. Bookmark mark = doc.Range.Bookmarks["Official"];
  4926. mark.Text = Official.TrimEnd('、');
  4927. }
  4928. //出访日期
  4929. if (doc.Range.Bookmarks["VisitDate"] != null)
  4930. {
  4931. Bookmark mark = doc.Range.Bookmarks["VisitDate"];
  4932. mark.Text = di.VisitStartDate.Year + "年"
  4933. + di.VisitStartDate.Month + "月"
  4934. + di.VisitStartDate.Day + "日"
  4935. + "至"
  4936. + di.VisitEndDate.Month + "月"
  4937. + di.VisitEndDate.Day + "日";
  4938. }
  4939. //请示范例
  4940. if (doc.Range.Bookmarks["Temp"] != null)
  4941. {
  4942. Bookmark mark = doc.Range.Bookmarks["Temp"];
  4943. mark.Text = bookmark;
  4944. }
  4945. //出访起止日期
  4946. if (doc.Range.Bookmarks["Duration"] != null)
  4947. {
  4948. Bookmark mark = doc.Range.Bookmarks["Duration"];
  4949. mark.Text = di.VisitStartDate.Year + "年"
  4950. + di.VisitStartDate.Month + "月"
  4951. + di.VisitStartDate.Day + "日"
  4952. + "至"
  4953. + di.VisitEndDate.Month + "月"
  4954. + di.VisitEndDate.Day + "日";
  4955. }
  4956. //出访天数
  4957. if (doc.Range.Bookmarks["Durationdays"] != null)
  4958. {
  4959. Bookmark mark = doc.Range.Bookmarks["Durationdays"];
  4960. mark.Text = di.VisitDays.ToString();
  4961. }
  4962. if (doc.Range.Bookmarks["Durationdays2"] != null)
  4963. {
  4964. Bookmark mark = doc.Range.Bookmarks["Durationdays2"];
  4965. mark.Text = di.VisitDays.ToString();
  4966. }
  4967. #region 根据黑屏代码获取国家呆的天数;获取路线
  4968. string result_CountryAndDay = "", result_Air = "";
  4969. if (airTable.Rows[airTable.Rows.Count - 1]["Day"].ToString() == "")
  4970. {
  4971. result_CountryAndDay = airTable.Rows[airTable.Rows.Count - 1]["Fliagtcode"].ToString();
  4972. result_Air = result_CountryAndDay;
  4973. }
  4974. else
  4975. {
  4976. string place_start, place_end;
  4977. DateTime time_start, time_end;
  4978. Res_ThreeCode three = null;
  4979. for (int i = 0; i < airTable.Rows.Count; i++)
  4980. {
  4981. //三字码实例
  4982. three = threeCodes.Find(x => x.Three == airTable.Rows[i]["Three"].ToString().Substring(0, 3));
  4983. if (three == null)
  4984. {
  4985. place_start = "【未收录三字码" + airTable.Rows[i]["Three"].ToString().Substring(0, 3) + ",请联系机票同事】";
  4986. }
  4987. else
  4988. {
  4989. if (string.IsNullOrEmpty(three.Country))
  4990. {
  4991. place_start = "【本三字码" + airTable.Rows[i]["Three"].ToString().Substring(0, 3) + "未录入国家信息,请联系机票同事】";
  4992. }
  4993. else
  4994. {
  4995. place_start = three.City;
  4996. }
  4997. }
  4998. three = threeCodes.Find(x => x.Three == airTable.Rows[i]["Three"].ToString().Substring(3, 3));
  4999. if (three == null)
  5000. {
  5001. place_end = "【未收录" + airTable.Rows[i]["Three"].ToString().Substring(0, 3) + ",请联系机票同事】";
  5002. }
  5003. else
  5004. {
  5005. if (string.IsNullOrEmpty(three.Country))
  5006. {
  5007. place_end = "【本三字码" + airTable.Rows[i]["Three"].ToString().Substring(0, 3) + "未录入国家信息,请联系机票同事】";
  5008. }
  5009. else
  5010. {
  5011. place_end = three.City;
  5012. }
  5013. }
  5014. result_Air += place_start + "一" + place_end + "一";
  5015. //获取国家和呆的天数
  5016. if (i > 0 && i < airTable.Rows.Count - 1)
  5017. {
  5018. time_start = Convert.ToDateTime(airTable.Rows[i - 1]["Day"]);
  5019. time_end = Convert.ToDateTime(airTable.Rows[i]["Day"]);
  5020. TimeSpan daycount = time_end.Subtract(time_start);
  5021. result_CountryAndDay += place_start + daycount.Days + "天" + ",";
  5022. }
  5023. }
  5024. }
  5025. #endregion
  5026. //每个国家呆的天数
  5027. if (doc.Range.Bookmarks["CountryAndDay"] != null)
  5028. {
  5029. Bookmark mark = doc.Range.Bookmarks["CountryAndDay"];
  5030. mark.Text = result_CountryAndDay.TrimEnd(',');
  5031. }
  5032. #region 出访路线城市字符串去重
  5033. result_Air = result_Air.TrimEnd('一');
  5034. string[] airTemp = result_Air.Split('一');
  5035. airTemp = airTemp.Distinct().ToArray();
  5036. result_Air = "";
  5037. foreach (string str in airTemp)
  5038. {
  5039. result_Air += str + "一";
  5040. }
  5041. result_Air = result_Air + airTemp[0];
  5042. #endregion
  5043. //出访路线
  5044. if (doc.Range.Bookmarks["Air"] != null)
  5045. {
  5046. Bookmark mark = doc.Range.Bookmarks["Air"];
  5047. mark.Text = result_Air;
  5048. }
  5049. #endregion
  5050. #region 客户名单
  5051. NodeCollection allTables = doc.GetChildNodes(NodeType.Table, true);
  5052. Aspose.Words.Tables.Table tableClient = allTables[0] as Aspose.Words.Tables.Table;
  5053. if (clientList == null || clientList.Count == 0)
  5054. {
  5055. builder.MoveToCell(0, 1, 0, 0);
  5056. builder.Write("【本团尚未录入客户名单,请联系主管!】");
  5057. }
  5058. else
  5059. {
  5060. for (int i = 0; i < clientList.Count; i++)
  5061. {
  5062. builder.MoveToCell(0, i + 1, 0, 0);
  5063. builder.Write((i + 1).ToString());
  5064. builder.MoveToCell(0, i + 1, 1, 0);
  5065. builder.Write(clientList[i].LastName.ToString() + clientList[i].FirstName.ToString());
  5066. builder.MoveToCell(0, i + 1, 2, 0);
  5067. builder.Write(clientList[i].Sex.ToString());
  5068. builder.MoveToCell(0, i + 1, 3, 0);
  5069. builder.Write(clientList[i].BirthDay);
  5070. builder.MoveToCell(0, i + 1, 4, 0);
  5071. builder.Write(clientList[i].CompanyFullName + clientList[i].Job.ToString());
  5072. }
  5073. }
  5074. while (tableClient.Rows.Count > clientList.Count + 1)
  5075. {
  5076. tableClient.Rows.RemoveAt(clientList.Count + 1);
  5077. }
  5078. #endregion
  5079. #region 商邀行程
  5080. string content = "", temp1 = "", temp2 = "";
  5081. //获取数据,放到datatable
  5082. var listapt = await _sqlSugar.Queryable<Grp_ApprovalTravel>()
  5083. .LeftJoin<Grp_ApprovalTravelDetails>((at, atd) => at.Id == atd.ParentId)
  5084. .Where((at, atd) => at.IsDel == 0 && at.Diid == dto.DiId)
  5085. .Select((at, atd) => new
  5086. {
  5087. at.Id,
  5088. at.Date,
  5089. atd.Time,
  5090. atd.Details
  5091. })
  5092. .ToListAsync();
  5093. if (listapt == null || listapt.Count == 0)
  5094. {
  5095. content = "尚未生成商邀行程";
  5096. }
  5097. else
  5098. {
  5099. for (int i = 0; i < listapt.Count; i++)
  5100. {
  5101. content = content + " " + listapt[i].Date + "\r\n";
  5102. temp1 = listapt[i].Time;
  5103. temp2 = listapt[i].Details;
  5104. if (!string.IsNullOrEmpty(temp1))
  5105. {
  5106. string[] str = temp1.Replace("\r\n", " ").Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
  5107. string[] str2 = temp2.Replace("\r\n", " ").Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
  5108. for (int j = 0; j < str.Length; j++)
  5109. {
  5110. content = content + " " + str[j] + str2[j] + "\r\n";
  5111. }
  5112. }
  5113. }
  5114. }
  5115. if (doc.Range.Bookmarks["Content"] != null)
  5116. {
  5117. Bookmark mark = doc.Range.Bookmarks["Content"];
  5118. mark.Text = content;
  5119. }
  5120. while (tableClient.Rows.Count > 1 + clientList.Count)
  5121. {
  5122. tableClient.Rows.RemoveAt(1 + clientList.Count);
  5123. }
  5124. #endregion
  5125. #endregion
  5126. string strFileName = $"/AskData/省外办出访请示{Guid.NewGuid().ToString()}.doc";
  5127. doc.Save(AppSettingsHelper.Get("WordBasePath") + strFileName); //"C:\\Server\\File\\OA2023\\Office\\Word" + strFileName
  5128. var url = AppSettingsHelper.Get("WordBaseUrl") + AppSettingsHelper.Get("WordFtpPath") + strFileName; //"C:\\Server\\File\\OA2023\\Office\\Word" + strFileName
  5129. return Ok(JsonView(true, "操作成功!", new { url = url }));
  5130. }
  5131. /// <summary>
  5132. /// 请示资料信息
  5133. /// 市外办下载
  5134. /// </summary>
  5135. /// <param name="dto"></param>
  5136. /// <returns></returns>
  5137. [HttpPost]
  5138. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5139. public async Task<IActionResult> AskDataCityFAOPFile(AskDataProvinceFileDto dto)
  5140. {
  5141. if (dto.DataIdItem.Length < 1) return Ok(JsonView(false, $"请传入有效的数据Id集合!"));
  5142. if (dto.DiId < 1) return Ok(JsonView(false, $"请传入有效的数据DiId参数!"));
  5143. //大写数字序号
  5144. string[] num = { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十" ,
  5145. "十一","十二","十三","十四","十五","十六","十七","十八","十九","二十",
  5146. "二十一","二十二","二十三","二十四","二十五","二十六","二十七","二十八","二十九","三十",
  5147. "三十一","三十二","三十三","三十四","三十五","三十六","三十七","三十八","三十九","四十"};
  5148. //数据源
  5149. var idItem = dto.DataIdItem.OrderBy(x => x);
  5150. var askDatas = await _sqlSugar.Queryable<Res_AskData>().Where(x => x.IsDel == 0 && idItem.Contains(x.Id)).ToListAsync();
  5151. //书签名
  5152. string Area = "",
  5153. Official = "";
  5154. //表格数据源
  5155. DataTable dt = new DataTable();
  5156. dt.Columns.Add("Country", typeof(string));
  5157. dt.Columns.Add("TalkCase", typeof(string));
  5158. int id = 0;
  5159. int TalkcaseOrder = 0;
  5160. int RowOrder = 0;
  5161. //填充数据
  5162. for (int i = 0; i < askDatas.Count; i++)
  5163. {
  5164. var ad = askDatas[i];
  5165. Area = Area + ad.Country + ad.Area + "、";
  5166. Official = Official + ad.UnitName + "、";
  5167. //填充表格数据源
  5168. DataRow dr = dt.NewRow();
  5169. if (i > 0)
  5170. {
  5171. var adtemp = askDatas[i - 1];
  5172. if (ad.Country == adtemp.Country)
  5173. {
  5174. TalkcaseOrder++;
  5175. dt.Rows[RowOrder]["TalkCase"] = dt.Rows[RowOrder]["TalkCase"] + "\r\n" + (1 + TalkcaseOrder).ToString() + "、" + ad.TalkCase;
  5176. }
  5177. else
  5178. {
  5179. RowOrder++;
  5180. dr = dt.NewRow();
  5181. dr["Country"] = "(" + num[RowOrder] + ")" + ad.Country;
  5182. dr["TalkCase"] = "1、" + ad.TalkCase;
  5183. dt.Rows.Add(dr);
  5184. TalkcaseOrder = 0;
  5185. }
  5186. }
  5187. else
  5188. {
  5189. dr["Country"] = "(" + num[i] + ")" + ad.Country;
  5190. dr["TalkCase"] = "1、" + ad.TalkCase;
  5191. dt.Rows.Add(dr);
  5192. }
  5193. id = ad.Id;
  5194. }
  5195. //模板路径
  5196. var tempPath = AppSettingsHelper.Get("WordBasePath") + "Template/市外办出访请示.doc";
  5197. //载入模板
  5198. Aspose.Words.Document doc = new Aspose.Words.Document(tempPath);
  5199. #region 填充word内容
  5200. #region 填充请示内容
  5201. //利用DocumentBuilder处理表格或是书签
  5202. Aspose.Words.DocumentBuilder builder = new DocumentBuilder(doc);
  5203. string bookmark = "";
  5204. try
  5205. {
  5206. for (int i = 0; i < dt.Rows.Count; i++)
  5207. {
  5208. bookmark = bookmark
  5209. + dt.Rows[i]["Country"].ToString() + "\r\n"
  5210. + dt.Rows[i]["TalkCase"].ToString() + "\r\n";
  5211. }
  5212. }
  5213. catch
  5214. {
  5215. }
  5216. #endregion
  5217. #region 填充word模板书签内容
  5218. //团组信息
  5219. var di = await _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && x.Id == dto.DiId).FirstAsync();
  5220. //接团客户名单实例
  5221. string client_sql = string.Format(@"
  5222. SELECT
  5223. tcl.Id,
  5224. tcl.DiId,
  5225. tcl.IsAccompany,
  5226. temp.*,
  5227. u.CnName AS Operator,
  5228. tcl.CreateTime AS OperatingTime
  5229. FROM
  5230. Grp_TourClientList tcl
  5231. LEFT JOIN (
  5232. SELECT
  5233. dc.Id AS DcId,
  5234. dc.LastName,
  5235. dc.FirstName,
  5236. ccom.CompanyFullName,
  5237. dc.Job,
  5238. cc.CertNo AS IDCardNo,
  5239. dc.Sex,
  5240. dc.BirthDay
  5241. FROM
  5242. Crm_DeleClient dc
  5243. LEFT JOIN Crm_CustomerCompany ccom ON dc.CrmCompanyId = ccom.Id
  5244. AND ccom.IsDel = 0
  5245. LEFT JOIN Crm_CustomerCert cc ON dc.Id = cc.DcId
  5246. AND cc.SdId = 773
  5247. AND cc.IsDel = 0
  5248. WHERE
  5249. dc.IsDel = 0
  5250. ) temp ON temp.DcId = tcl.ClientId
  5251. LEFT JOIN Sys_Users u ON tcl.CreateUserId = u.Id
  5252. WHERE
  5253. tcl.IsDel = 0
  5254. AND tcl.DiId = {0}", dto.DiId);
  5255. var clientList = await _sqlSugar.SqlQueryable<TourClientListDetailsView>(client_sql).ToListAsync();
  5256. //机票代码实例
  5257. DataTable airTable = GeneralMethod.GetTableByBlackCode(dto.DiId);
  5258. //三字码
  5259. var threeCodes = await _sqlSugar.Queryable<Res_ThreeCode>().Where(x => x.IsDel == 0).ToListAsync();
  5260. //团名
  5261. if (doc.Range.Bookmarks["TeamName"] != null)
  5262. {
  5263. Bookmark mark = doc.Range.Bookmarks["TeamName"];
  5264. mark.Text = di.TeamName;
  5265. }
  5266. //团长名
  5267. if (doc.Range.Bookmarks["ClientName2"] != null)
  5268. {
  5269. Bookmark mark = doc.Range.Bookmarks["ClientName2"];
  5270. if (clientList == null || clientList.Count == 0)
  5271. {
  5272. mark.Text = "【本团尚未录入客户名单,请联系主管!】";
  5273. }
  5274. else
  5275. {
  5276. mark.Text = clientList[0].CompanyFullName + clientList[0].Job + clientList[0].LastName + clientList[0].FirstName;
  5277. }
  5278. }
  5279. if (doc.Range.Bookmarks["ClientName"] != null)
  5280. {
  5281. Bookmark mark = doc.Range.Bookmarks["ClientName"];
  5282. if (clientList == null || clientList.Count == 0)
  5283. {
  5284. mark.Text = "【本团尚未录入客户名单,请联系主管!】";
  5285. }
  5286. else
  5287. {
  5288. mark.Text = clientList[0].CompanyFullName + clientList[0].Job + clientList[0].LastName + clientList[0].FirstName;
  5289. }
  5290. }
  5291. //跟团人数
  5292. if (doc.Range.Bookmarks["ClientNumber2"] != null)
  5293. {
  5294. Bookmark mark = doc.Range.Bookmarks["ClientNumber2"];
  5295. mark.Text = di.VisitPNumber.ToString();
  5296. }
  5297. if (doc.Range.Bookmarks["ClientNumber"] != null)
  5298. {
  5299. Bookmark mark = doc.Range.Bookmarks["ClientNumber"];
  5300. mark.Text = di.VisitPNumber.ToString();
  5301. }
  5302. //地区
  5303. if (doc.Range.Bookmarks["Area"] != null)
  5304. {
  5305. Bookmark mark = doc.Range.Bookmarks["Area"];
  5306. mark.Text = Area.TrimEnd('、');
  5307. }
  5308. if (doc.Range.Bookmarks["Area2"] != null)
  5309. {
  5310. Bookmark mark = doc.Range.Bookmarks["Area2"];
  5311. mark.Text = Area.TrimEnd('、');
  5312. }
  5313. //出访目的
  5314. if (doc.Range.Bookmarks["Destination2"] != null)
  5315. {
  5316. Bookmark mark = doc.Range.Bookmarks["Destination2"];
  5317. mark.Text = di.VisitPurpose;
  5318. }
  5319. if (doc.Range.Bookmarks["Destination"] != null)
  5320. {
  5321. Bookmark mark = doc.Range.Bookmarks["Destination"];
  5322. mark.Text = di.VisitPurpose;
  5323. }
  5324. //邀请方
  5325. if (doc.Range.Bookmarks["Official"] != null)
  5326. {
  5327. Bookmark mark = doc.Range.Bookmarks["Official"];
  5328. mark.Text = Official.TrimEnd('、');
  5329. }
  5330. //出访日期
  5331. if (doc.Range.Bookmarks["VisitDate"] != null)
  5332. {
  5333. Bookmark mark = doc.Range.Bookmarks["VisitDate"];
  5334. mark.Text = di.VisitStartDate.Year + "年"
  5335. + di.VisitStartDate.Month + "月"
  5336. + di.VisitStartDate.Day + "日"
  5337. + "至"
  5338. + di.VisitEndDate.Month + "月"
  5339. + di.VisitEndDate.Day + "日";
  5340. }
  5341. //请示范例
  5342. if (doc.Range.Bookmarks["Temp"] != null)
  5343. {
  5344. Bookmark mark = doc.Range.Bookmarks["Temp"];
  5345. mark.Text = bookmark;
  5346. }
  5347. //出访起止日期
  5348. if (doc.Range.Bookmarks["Duration"] != null)
  5349. {
  5350. Bookmark mark = doc.Range.Bookmarks["Duration"];
  5351. mark.Text = di.VisitStartDate.Year + "年"
  5352. + di.VisitStartDate.Month + "月"
  5353. + di.VisitStartDate.Day + "日"
  5354. + "至"
  5355. + di.VisitEndDate.Month + "月"
  5356. + di.VisitEndDate.Day + "日";
  5357. }
  5358. //出访天数
  5359. if (doc.Range.Bookmarks["Durationdays"] != null)
  5360. {
  5361. Bookmark mark = doc.Range.Bookmarks["Durationdays"];
  5362. mark.Text = di.VisitDays.ToString();
  5363. }
  5364. if (doc.Range.Bookmarks["Durationdays2"] != null)
  5365. {
  5366. Bookmark mark = doc.Range.Bookmarks["Durationdays2"];
  5367. mark.Text = di.VisitDays.ToString();
  5368. }
  5369. #region 根据黑屏代码获取国家呆的天数;获取路线
  5370. string result_CountryAndDay = "", result_Air = "";
  5371. if (airTable.Rows[airTable.Rows.Count - 1]["Day"].ToString() == "")
  5372. {
  5373. result_CountryAndDay = airTable.Rows[airTable.Rows.Count - 1]["Fliagtcode"].ToString();
  5374. result_Air = result_CountryAndDay;
  5375. }
  5376. else
  5377. {
  5378. string place_start, place_end;
  5379. DateTime time_start, time_end;
  5380. Res_ThreeCode three = null;
  5381. for (int i = 0; i < airTable.Rows.Count; i++)
  5382. {
  5383. //三字码实例
  5384. three = threeCodes.Find(x => x.Three == airTable.Rows[i]["Three"].ToString().Substring(0, 3));
  5385. if (three == null)
  5386. {
  5387. place_start = "【未收录三字码" + airTable.Rows[i]["Three"].ToString().Substring(0, 3) + ",请联系机票同事】";
  5388. }
  5389. else
  5390. {
  5391. if (string.IsNullOrEmpty(three.Country))
  5392. {
  5393. place_start = "【本三字码" + airTable.Rows[i]["Three"].ToString().Substring(0, 3) + "未录入国家信息,请联系机票同事】";
  5394. }
  5395. else
  5396. {
  5397. place_start = three.City;
  5398. }
  5399. }
  5400. three = threeCodes.Find(x => x.Three == airTable.Rows[i]["Three"].ToString().Substring(3, 3));
  5401. if (three == null)
  5402. {
  5403. place_end = "【未收录" + airTable.Rows[i]["Three"].ToString().Substring(0, 3) + ",请联系机票同事】";
  5404. }
  5405. else
  5406. {
  5407. if (string.IsNullOrEmpty(three.Country))
  5408. {
  5409. place_end = "【本三字码" + airTable.Rows[i]["Three"].ToString().Substring(0, 3) + "未录入国家信息,请联系机票同事】";
  5410. }
  5411. else
  5412. {
  5413. place_end = three.City;
  5414. }
  5415. }
  5416. result_Air += place_start + "一" + place_end + "一";
  5417. //获取国家和呆的天数
  5418. if (i > 0 && i < airTable.Rows.Count - 1)
  5419. {
  5420. time_start = Convert.ToDateTime(airTable.Rows[i - 1]["Day"]);
  5421. time_end = Convert.ToDateTime(airTable.Rows[i]["Day"]);
  5422. TimeSpan daycount = time_end.Subtract(time_start);
  5423. result_CountryAndDay += place_start + daycount.Days + "天" + ",";
  5424. }
  5425. }
  5426. }
  5427. #endregion
  5428. //每个国家呆的天数
  5429. if (doc.Range.Bookmarks["CountryAndDay"] != null)
  5430. {
  5431. Bookmark mark = doc.Range.Bookmarks["CountryAndDay"];
  5432. mark.Text = result_CountryAndDay.TrimEnd(',');
  5433. }
  5434. #region 出访路线城市字符串去重
  5435. result_Air = result_Air.TrimEnd('一');
  5436. string[] airTemp = result_Air.Split('一');
  5437. airTemp = airTemp.Distinct().ToArray();
  5438. result_Air = "";
  5439. foreach (string str in airTemp)
  5440. {
  5441. result_Air += str + "一";
  5442. }
  5443. result_Air = result_Air + airTemp[0];
  5444. #endregion
  5445. //出访路线
  5446. if (doc.Range.Bookmarks["Air"] != null)
  5447. {
  5448. Bookmark mark = doc.Range.Bookmarks["Air"];
  5449. mark.Text = result_Air;
  5450. }
  5451. #endregion
  5452. #region 客户名单
  5453. NodeCollection allTables = doc.GetChildNodes(NodeType.Table, true);
  5454. Aspose.Words.Tables.Table tableClient = allTables[0] as Aspose.Words.Tables.Table;
  5455. if (clientList == null || clientList.Count == 0)
  5456. {
  5457. builder.MoveToCell(0, 1, 0, 0);
  5458. builder.Write("【本团尚未录入客户名单,请联系主管!】");
  5459. }
  5460. else
  5461. {
  5462. for (int i = 0; i < clientList.Count; i++)
  5463. {
  5464. builder.MoveToCell(0, i + 1, 0, 0);
  5465. builder.Write((i + 1).ToString());
  5466. builder.MoveToCell(0, i + 1, 1, 0);
  5467. builder.Write(clientList[i].LastName.ToString() + clientList[i].FirstName.ToString());
  5468. builder.MoveToCell(0, i + 1, 2, 0);
  5469. builder.Write(clientList[i].Sex.ToString());
  5470. builder.MoveToCell(0, i + 1, 3, 0);
  5471. builder.Write(clientList[i].BirthDay);
  5472. builder.MoveToCell(0, i + 1, 4, 0);
  5473. builder.Write(clientList[i].CompanyFullName + clientList[i].Job.ToString());
  5474. }
  5475. }
  5476. while (tableClient.Rows.Count > clientList.Count + 1)
  5477. {
  5478. tableClient.Rows.RemoveAt(clientList.Count + 1);
  5479. }
  5480. #endregion
  5481. #region 商邀行程
  5482. string content = "", temp1 = "", temp2 = "";
  5483. //获取数据,放到datatable
  5484. var listapt = await _sqlSugar.Queryable<Grp_ApprovalTravel>()
  5485. .LeftJoin<Grp_ApprovalTravelDetails>((at, atd) => at.Id == atd.ParentId)
  5486. .Where((at, atd) => at.IsDel == 0 && at.Diid == dto.DiId)
  5487. .Select((at, atd) => new
  5488. {
  5489. at.Id,
  5490. at.Date,
  5491. atd.Time,
  5492. atd.Details
  5493. })
  5494. .ToListAsync();
  5495. if (listapt == null || listapt.Count == 0)
  5496. {
  5497. content = "尚未生成商邀行程";
  5498. }
  5499. else
  5500. {
  5501. for (int i = 0; i < listapt.Count; i++)
  5502. {
  5503. content = content + " " + listapt[i].Date + "\r\n";
  5504. temp1 = listapt[i].Time;
  5505. temp2 = listapt[i].Details;
  5506. if (!string.IsNullOrEmpty(temp1))
  5507. {
  5508. string[] str = temp1.Replace("\r\n", " ").Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
  5509. string[] str2 = temp2.Replace("\r\n", " ").Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
  5510. for (int j = 0; j < str.Length; j++)
  5511. {
  5512. content = content + " " + str[j] + str2[j] + "\r\n";
  5513. }
  5514. }
  5515. }
  5516. }
  5517. if (doc.Range.Bookmarks["Content"] != null)
  5518. {
  5519. Bookmark mark = doc.Range.Bookmarks["Content"];
  5520. mark.Text = content;
  5521. }
  5522. while (tableClient.Rows.Count > 1 + clientList.Count)
  5523. {
  5524. tableClient.Rows.RemoveAt(1 + clientList.Count);
  5525. }
  5526. #endregion
  5527. #endregion
  5528. string strFileName = $"/AskData/市外办出访请示{Guid.NewGuid().ToString()}.doc";
  5529. doc.Save(AppSettingsHelper.Get("WordBasePath") + strFileName); //"C:\\Server\\File\\OA2023\\Office\\Word" + strFileName
  5530. var url = AppSettingsHelper.Get("WordBaseUrl") + AppSettingsHelper.Get("WordFtpPath") + strFileName; //"C:\\Server\\File\\OA2023\\Office\\Word" + strFileName
  5531. return Ok(JsonView(true, "操作成功!", new { url = url }));
  5532. }
  5533. #endregion
  5534. #region 机票黑屏代码
  5535. /// <summary>
  5536. /// 根据团组Id查询黑屏代码列表
  5537. /// </summary>
  5538. /// <param name="dto"></param>
  5539. /// <returns></returns>
  5540. [HttpPost]
  5541. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5542. public async Task<IActionResult> QueryTicketBlackCodeByDiId(QueryTicketBlackCodeByDiIdDto dto)
  5543. {
  5544. Result groupData = await _ticketBlackCodeRep.QueryTicketBlackCodeByDiId(dto);
  5545. if (groupData.Code != 0)
  5546. {
  5547. return Ok(JsonView(false, groupData.Msg));
  5548. }
  5549. return Ok(JsonView(true, groupData.Msg, groupData.Data));
  5550. }
  5551. /// <summary>
  5552. /// 根据黑屏代码数据Id查询信息
  5553. /// </summary>
  5554. /// <param name="dto"></param>
  5555. /// <returns></returns>
  5556. [HttpPost]
  5557. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5558. public async Task<IActionResult> QueryTicketBlackCodeById(QueryTicketBlackCodeByIdDto dto)
  5559. {
  5560. Result groupData = await _ticketBlackCodeRep.QueryTicketBlackCodeById(dto);
  5561. if (groupData.Code != 0)
  5562. {
  5563. return Ok(JsonView(false, groupData.Msg));
  5564. }
  5565. return Ok(JsonView(true, groupData.Msg, groupData.Data));
  5566. }
  5567. /// <summary>
  5568. /// 黑屏代码操作(Status:1.新增,2.修改)
  5569. /// </summary>
  5570. /// <param name="dto"></param>
  5571. /// <returns></returns>
  5572. [HttpPost]
  5573. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5574. public async Task<IActionResult> OpTicketBlackCode(OpTicketBlackCodeDto dto)
  5575. {
  5576. Result groupData = await _ticketBlackCodeRep.OpTicketBlackCode(dto);
  5577. if (groupData.Code != 0)
  5578. {
  5579. return Ok(JsonView(false, groupData.Msg));
  5580. }
  5581. try
  5582. {
  5583. var tongzhi = _ticketBlackCodeRep.DescBlackToVisa(dto.DiId);
  5584. if (tongzhi.Code == 0)
  5585. {
  5586. var info = tongzhi.Data.GetType().GetProperty("info").GetValue(tongzhi.Data) as List<string>;
  5587. var data = tongzhi.Data.GetType().GetProperty("data").GetValue(tongzhi.Data) as List<CountryDataTime>;
  5588. if (data != null)
  5589. await AppNoticeLibrary.SendUserMsg_blackAirInfo_ToVisaUser(dto.DiId, data);
  5590. }
  5591. //行程代码变更通知
  5592. await AppNoticeLibrary.SendUserMsg_GroupShare_ToDP(dto.DiId, dto.CreateUserId);
  5593. }
  5594. catch (Exception)
  5595. {
  5596. throw;
  5597. }
  5598. return Ok(JsonView(true, groupData.Msg, groupData.Data));
  5599. }
  5600. /// <summary>
  5601. /// 删除黑屏代码
  5602. /// </summary>
  5603. /// <param name="dto"></param>
  5604. /// <returns></returns>
  5605. [HttpPost]
  5606. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5607. public async Task<IActionResult> DelTicketBlackCode(DelBaseDto dto)
  5608. {
  5609. var res = await _ticketBlackCodeRep.SoftDeleteByIdAsync<Air_TicketBlackCode>(dto.Id.ToString(), dto.DeleteUserId);
  5610. if (!res)
  5611. {
  5612. return Ok(JsonView(false, "删除失败"));
  5613. }
  5614. return Ok(JsonView(true, "删除成功!"));
  5615. }
  5616. #endregion
  5617. #region 翻译人员
  5618. /// <summary>
  5619. /// 翻译人员库
  5620. /// Init
  5621. /// </summary>
  5622. /// <returns></returns>
  5623. [HttpGet]
  5624. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5625. public async Task<IActionResult> TranslatorLibraryInit()
  5626. {
  5627. var currencyData = await _sqlSugar.Queryable<Sys_SetData>()
  5628. .Where(x => x.IsDel == 0 && x.STid == 66)
  5629. .Select(x => new
  5630. {
  5631. x.Id,
  5632. x.Name,
  5633. })
  5634. .ToListAsync();
  5635. var officialDutyData = await _sqlSugar.Queryable<Res_OfficialActivities>()
  5636. .LeftJoin<Grp_DelegationInfo>((oa, di) => oa.DiId == di.Id)
  5637. .Where((oa, di) => oa.IsDel == 0)
  5638. .Select((oa, di) => new
  5639. {
  5640. oa.Id,
  5641. oa.Client,
  5642. oa.DiId,
  5643. di.TeamName
  5644. })
  5645. .ToListAsync();
  5646. var officialDutyData1 = officialDutyData.GroupBy(x => x.DiId)
  5647. .Select(g => new
  5648. {
  5649. id = g.Key,
  5650. label = g.FirstOrDefault()?.TeamName ?? "-",
  5651. children = g.Select(g1 => new { id = g1.Id, label = g1.Client }).ToList()
  5652. })
  5653. .ToList();
  5654. var view = new
  5655. {
  5656. currencyData,
  5657. officialDutyData = officialDutyData1
  5658. };
  5659. return Ok(JsonView(view));
  5660. }
  5661. /// <summary>
  5662. /// 翻译人员库
  5663. /// 详情
  5664. /// </summary>
  5665. /// <param name="id"></param>
  5666. /// <returns></returns>
  5667. [HttpGet("id")]
  5668. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5669. public async Task<IActionResult> TranslatorLibraryInfo(int id)
  5670. {
  5671. if (id < 1) return Ok(JsonView(false, "请传入有效的Id!"));
  5672. var info = await _translatorRep.Query(x => x.Id == id).FirstAsync();
  5673. EncryptionProcessor.DecryptProperties(info);
  5674. var view = _mapper.Map<TranslatorLibraryInfoView>(info);
  5675. //var data1 = await _sqlSugar.Queryable<Grp_OfficialDutyLinkTranslator>().Where(x => x.TranslatorId == id).Select(x => x.Id).ToArrayAsync();
  5676. view.OfficialDutyIdItem = await _sqlSugar
  5677. .Queryable<Grp_OfficialDutyLinkTranslator>()
  5678. .Where(x => x.IsDel == 0 && x.TranslatorId == id)
  5679. .Select(x => x.OfficialDutyId)
  5680. .ToArrayAsync();
  5681. return Ok(JsonView(view));
  5682. }
  5683. /// <summary>
  5684. /// 翻译人员库
  5685. /// Item
  5686. /// </summary>
  5687. /// <param name="dto"></param>
  5688. /// <returns></returns>
  5689. [HttpPost]
  5690. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5691. public async Task<IActionResult> TranslatorLibraryItem(TranslatorLibraryItemDto dto)
  5692. {
  5693. if (dto.PortType < 1 || dto.PortType > 3) return Ok(JsonView(false, MsgTips.Port));
  5694. var name = AesEncryptionHelper.Encrypt(dto.Name);
  5695. RefAsync<int> total = 0;
  5696. var view = await _sqlSugar.Queryable<Res_TranslatorLibrary>()
  5697. .Where(x => x.IsDel == 0)
  5698. .WhereIF(!string.IsNullOrEmpty(name), x => x.Name.Contains(name))
  5699. .Select(x => new TranslatorLibraryItemView()
  5700. {
  5701. Id = x.Id,
  5702. Area = x.Area,
  5703. Name = x.Name,
  5704. Sex = x.Sex == 0 ? "未设置" : x.Sex == 1 ? "男" : "女",
  5705. Tel = x.Tel,
  5706. Email = x.Email,
  5707. WechatNo = x.WechatNo,
  5708. Language = x.Language,
  5709. Price = x.Price,
  5710. Currency = SqlFunc.Subqueryable<Sys_SetData>().Where(x1 => x1.Id == x.Currency).Select(x1 => x1.Name) ?? "-",
  5711. CreateUserName = SqlFunc.Subqueryable<Sys_Users>().Where(x1 => x1.Id == x.CreateUserId).Select(x1 => x1.CnName) ?? "-",
  5712. LastUpddateTime = x.LastUpdateTime,
  5713. CreateTime = x.CreateTime,
  5714. Remark = x.Remark
  5715. })
  5716. .OrderByDescending(x => x.CreateTime)
  5717. .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
  5718. foreach (var item in view) EncryptionProcessor.DecryptProperties(item);
  5719. return Ok(JsonView(view, total));
  5720. }
  5721. /// <summary>
  5722. /// 翻译人员库
  5723. /// OP
  5724. /// </summary>
  5725. /// <param name="dto"></param>
  5726. /// <returns></returns>
  5727. [HttpPost]
  5728. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5729. public async Task<IActionResult> TranslatorLibraryOp([FromForm] TranslatorLibraryOpDto dto)
  5730. {
  5731. if (dto.PortType < 1 || dto.PortType > 3) return Ok(JsonView(false, MsgTips.Port));
  5732. if (dto.Status < 1 || dto.Status > 2) return Ok(JsonView(false, MsgTips.Status));
  5733. var currUserInfo = JwtHelper.SerializeJwt(HttpContext.Request.Headers.Authorization);
  5734. if (currUserInfo == null) return Ok(JsonView(false, "请传入token!"));
  5735. var fileNames = new List<string>();
  5736. //D:\FTP\File\OA2023\Office\GrpFile\TranslatorLibrary
  5737. var fileBasePath = $"{AppSettingsHelper.Get("GrpFileBasePath")}TranslatorLibrary";
  5738. #region 保存文件
  5739. if (dto.Files != null)
  5740. {
  5741. if (!System.IO.Directory.Exists(fileBasePath))
  5742. {
  5743. System.IO.Directory.CreateDirectory(fileBasePath);
  5744. }
  5745. foreach (var item in dto.Files)
  5746. {
  5747. if (item.Length < 1) continue;
  5748. var file = item;
  5749. // 将文件保存到指定位置
  5750. var filePath = Path.Combine(fileBasePath, file.FileName);
  5751. using (var stream = new FileStream(filePath, FileMode.Create))
  5752. {
  5753. await file.CopyToAsync(stream);
  5754. }
  5755. //验证文件是否上传成功
  5756. if (!System.IO.File.Exists(filePath))
  5757. {
  5758. foreach (var filePathStr in fileNames)
  5759. {
  5760. System.IO.File.Delete(Path.Combine(fileBasePath, filePathStr));
  5761. }
  5762. return Ok(JsonView(false, "文件上传失败!"));
  5763. }
  5764. fileNames.Add(file.FileName);
  5765. }
  5766. }
  5767. #endregion
  5768. #region 参数处理
  5769. EncryptionProcessor.EncryptProperties(dto);
  5770. var translatorInfo = _mapper.Map<Res_TranslatorLibrary>(dto);
  5771. translatorInfo.LastUpdateTime = translatorInfo.CreateTime;
  5772. translatorInfo.CreateUserId = currUserInfo.UserId;
  5773. #endregion
  5774. _sqlSugar.BeginTran();
  5775. if (dto.Status == 1)
  5776. {
  5777. //验证重复
  5778. var info = await _translatorRep.Query(x => x.Area.Equals(dto.Area) && x.Name.Equals(dto.Name)).FirstAsync();
  5779. if (info != null) return Ok(JsonView(false, "该条数据已存在!"));
  5780. if (fileNames.Count > 0)
  5781. {
  5782. translatorInfo.Files = AesEncryptionHelper.Encrypt(JsonConvert.SerializeObject(fileNames));
  5783. }
  5784. var id = await _translatorRep.AddAsync(translatorInfo);
  5785. if (id > 0)
  5786. {
  5787. #region 新增(公务信息关联翻译人员) 关联信息
  5788. if (dto.officialDutyIdItem != null && dto.officialDutyIdItem.Length > 0)
  5789. {
  5790. var officialDutyLinkTranslators = new List<Grp_OfficialDutyLinkTranslator>();
  5791. foreach (var officialDutyId in dto.officialDutyIdItem)
  5792. {
  5793. officialDutyLinkTranslators.Add(new Grp_OfficialDutyLinkTranslator()
  5794. {
  5795. TranslatorId = id,
  5796. OfficialDutyId = officialDutyId,
  5797. CreateUserId = currUserInfo.UserId,
  5798. Remark = $"翻译人员库-->添加"
  5799. });
  5800. }
  5801. if (officialDutyLinkTranslators.Count > 0)
  5802. {
  5803. await _sqlSugar.Insertable(officialDutyLinkTranslators).ExecuteCommandAsync();
  5804. }
  5805. }
  5806. #endregion
  5807. _sqlSugar.CommitTran();
  5808. return Ok(JsonView(true));
  5809. }
  5810. }
  5811. else if (dto.Status == 2)
  5812. {
  5813. var info = await _translatorRep.Query(x => x.Id == dto.Id).FirstAsync();
  5814. if (info != null)
  5815. {
  5816. if (!string.IsNullOrEmpty(info.Files))
  5817. {
  5818. try
  5819. {
  5820. var selectFiles = JsonConvert.DeserializeObject<List<string>>(info.Files);
  5821. fileNames.AddRange(selectFiles);
  5822. }
  5823. catch (Exception)
  5824. {
  5825. }
  5826. }
  5827. }
  5828. if (fileNames.Count > 0)
  5829. {
  5830. translatorInfo.Files = AesEncryptionHelper.Encrypt(JsonConvert.SerializeObject(fileNames));
  5831. }
  5832. translatorInfo.LastUpdateTime = DateTime.Now;
  5833. var upd = await _translatorRep
  5834. .UpdateAsync(x => x.Id == dto.Id, x => new Res_TranslatorLibrary()
  5835. {
  5836. Area = translatorInfo.Area,
  5837. Name = translatorInfo.Name,
  5838. Sex = translatorInfo.Sex,
  5839. Photo = translatorInfo.Photo,
  5840. Tel = translatorInfo.Tel,
  5841. Email = translatorInfo.Email,
  5842. WechatNo = translatorInfo.WechatNo,
  5843. OtherSocialAccounts = translatorInfo.OtherSocialAccounts,
  5844. Language = translatorInfo.Language,
  5845. Price = translatorInfo.Price,
  5846. Currency = translatorInfo.Currency,
  5847. Remark = translatorInfo.Remark,
  5848. Files = translatorInfo.Files,
  5849. LastUpdateTime = translatorInfo.LastUpdateTime,
  5850. LastUpdateUserId = translatorInfo.LastUpdateUserId,
  5851. });
  5852. if (upd)
  5853. {
  5854. #region 更新(公务信息关联翻译人员) 关联信息
  5855. var officialDutyLinkTranslators_select = await _sqlSugar.Queryable<Grp_OfficialDutyLinkTranslator>()
  5856. .Where(x => x.IsDel == 0 && x.TranslatorId == dto.Id)
  5857. .ToListAsync();
  5858. //删除
  5859. var officialDutyLinkTranslatorIds = officialDutyLinkTranslators_select.Select(x => x.Id).ToList();
  5860. if (officialDutyLinkTranslatorIds.Count > 0)
  5861. {
  5862. await _sqlSugar.Updateable<Grp_OfficialDutyLinkTranslator>()
  5863. .SetColumnsIF(officialDutyLinkTranslatorIds.Count > 0, x => new Grp_OfficialDutyLinkTranslator()
  5864. {
  5865. DeleteUserId = currUserInfo.UserId,
  5866. DeleteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  5867. IsDel = 1,
  5868. Remark = $"翻译人员库-->删除"
  5869. })
  5870. .Where(x => officialDutyLinkTranslatorIds.Contains(x.Id))
  5871. .ExecuteCommandAsync();
  5872. }
  5873. if (dto.officialDutyIdItem != null && dto.officialDutyIdItem.Length > 0)
  5874. {
  5875. //添加
  5876. var officialDutyLinkTranslators = new List<Grp_OfficialDutyLinkTranslator>();
  5877. foreach (var officialDutyId in dto.officialDutyIdItem)
  5878. {
  5879. officialDutyLinkTranslators.Add(new Grp_OfficialDutyLinkTranslator()
  5880. {
  5881. TranslatorId = dto.Id,
  5882. OfficialDutyId = officialDutyId,
  5883. CreateUserId = currUserInfo.UserId,
  5884. Remark = $"翻译人员库-->更新"
  5885. });
  5886. }
  5887. if (officialDutyLinkTranslators.Count > 0)
  5888. {
  5889. await _sqlSugar.Insertable(officialDutyLinkTranslators).ExecuteCommandAsync();
  5890. }
  5891. }
  5892. #endregion
  5893. _sqlSugar.CommitTran();
  5894. return Ok(JsonView(true));
  5895. }
  5896. }
  5897. _sqlSugar.RollbackTran();
  5898. return Ok(JsonView(false));
  5899. }
  5900. /// <summary>
  5901. /// 翻译人员库
  5902. /// Del
  5903. /// </summary>
  5904. /// <param name="id"></param>
  5905. /// <returns></returns>
  5906. [HttpDelete("id")]
  5907. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5908. public async Task<IActionResult> TranslatorLibraryDel(int id)
  5909. {
  5910. if (id < 1) return Ok(JsonView(false, MsgTips.Id));
  5911. var currUserInfo = JwtHelper.SerializeJwt(HttpContext.Request.Headers.Authorization);
  5912. if (currUserInfo == null) return Ok(JsonView(false, "请传入token!"));
  5913. _sqlSugar.BeginTran();
  5914. var upd = await _translatorRep.SoftDeleteByIdAsync<Res_TranslatorLibrary>(id.ToString(), currUserInfo.UserId);
  5915. if (!upd)
  5916. {
  5917. _sqlSugar.RollbackTran();
  5918. return Ok(JsonView(false));
  5919. }
  5920. #region 删除公务出访
  5921. await _sqlSugar.Updateable<Grp_OfficialDutyLinkTranslator>()
  5922. .SetColumns(x => new Grp_OfficialDutyLinkTranslator()
  5923. {
  5924. DeleteUserId = currUserInfo.UserId,
  5925. DeleteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
  5926. IsDel = 1,
  5927. Remark = $"翻译人员库-->删除"
  5928. })
  5929. .Where(x => x.TranslatorId == id)
  5930. .ExecuteCommandAsync();
  5931. #endregion
  5932. _sqlSugar.CommitTran();
  5933. return Ok(JsonView(true));
  5934. }
  5935. #endregion
  5936. #region 策划部供应商资料
  5937. /// <summary>
  5938. /// 策划部供应商资料
  5939. /// Init
  5940. /// </summary>
  5941. /// <returns></returns>
  5942. [HttpGet]
  5943. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5944. public async Task<IActionResult> MediaSupplierInit()
  5945. {
  5946. return Ok(await _mediaSupplierRep.Init());
  5947. }
  5948. /// <summary>
  5949. /// 策划部供应商资料
  5950. /// Info
  5951. /// </summary>
  5952. /// <param name="dto"></param>
  5953. /// <returns></returns>
  5954. [HttpPost]
  5955. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5956. public async Task<IActionResult> MediaSupplierInfo(MediaSupplierInfoDto dto)
  5957. {
  5958. if (!_portIds.Contains(dto.PortType)) return Ok(JsonView(false, MsgTips.Port));
  5959. if (dto.Id < 1) return Ok(JsonView(false, MsgTips.Port));
  5960. return Ok(await _mediaSupplierRep.Info(dto));
  5961. }
  5962. /// <summary>
  5963. /// 策划部供应商资料
  5964. /// 分页查询
  5965. /// </summary>
  5966. /// <param name="dto"></param>
  5967. /// <returns></returns>
  5968. [HttpPost]
  5969. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5970. public async Task<IActionResult> MediaSupplierPageItem(MediaSupplierPageItemDto dto)
  5971. {
  5972. if (!_portIds.Contains(dto.PortType)) return Ok(JsonView(false, MsgTips.Port));
  5973. return Ok(await _mediaSupplierRep.PageItem(dto));
  5974. }
  5975. /// <summary>
  5976. /// 策划部供应商资料
  5977. /// 操作(添加 Or 编辑)
  5978. /// </summary>
  5979. /// <param name="dto"></param>
  5980. /// <returns></returns>
  5981. [HttpPost]
  5982. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5983. public async Task<IActionResult> MediaSupplierOp(MediaSupplierAddOrEditDto dto)
  5984. {
  5985. var userId = dto.CurrUserId;
  5986. if (!_portIds.Contains(dto.PortType)) return Ok(JsonView(false, MsgTips.Port));
  5987. if (userId < 1) return Ok(JsonView(false, MsgTips.UserId));
  5988. return Ok(await _mediaSupplierRep.AddOrEdit(dto));
  5989. }
  5990. /// <summary>
  5991. /// 策划部供应商资料
  5992. /// 删除
  5993. /// </summary>
  5994. /// <param name="dto"></param>
  5995. /// <returns></returns>
  5996. [HttpPost]
  5997. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  5998. public async Task<IActionResult> MediaSupplierSoftDel(MediaSupplierSoftDelDto dto)
  5999. {
  6000. int userId = dto.CurrUserId, id = dto.Id;
  6001. if (!_portIds.Contains(dto.PortType)) return Ok(JsonView(false, MsgTips.Port));
  6002. if (userId < 1) return Ok(JsonView(false, MsgTips.UserId));
  6003. if (id < 1) return Ok(JsonView(false, MsgTips.Id));
  6004. return Ok(await _mediaSupplierRep.SoftDel(dto));
  6005. }
  6006. #endregion
  6007. #region 保险国家基础费用
  6008. /// <summary>
  6009. /// 保险国家基础费用
  6010. /// Info
  6011. /// </summary>
  6012. /// <param name="dto"></param>
  6013. /// <returns></returns>
  6014. [HttpPost]
  6015. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6016. public async Task<IActionResult> InsuranceCostInfo(InsuranceCostInfoDto dto)
  6017. {
  6018. if (!_portIds.Contains(dto.PortType)) return Ok(JsonView(false, MsgTips.Port));
  6019. if (dto.Id < 1) return Ok(JsonView(false, MsgTips.Port));
  6020. var id = dto.Id;
  6021. var info = await _sqlSugar.Queryable<Res_BasicInsuranceCost>()
  6022. .Where(x => x.Id == id && x.IsDel == 0)
  6023. .Select(x => new
  6024. {
  6025. x.Id,
  6026. x.IsSchengen,
  6027. x.CountryName,
  6028. x.Cost,
  6029. x.Remark,
  6030. CreateUserName = SqlFunc.Subqueryable<Sys_Users>().Where(s => s.Id == x.CreateUserId).Select(s => s.CnName),
  6031. x.CreateTime
  6032. })
  6033. .FirstAsync();
  6034. return Ok(JsonView(info));
  6035. }
  6036. /// <summary>
  6037. /// 保险国家基础费用
  6038. /// 分页查询
  6039. /// </summary>
  6040. /// <param name="dto"></param>
  6041. /// <returns></returns>
  6042. [HttpPost]
  6043. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6044. public async Task<IActionResult> InsuranceCostPageItem(InsuranceCostPageItemDto dto)
  6045. {
  6046. if (!_portIds.Contains(dto.PortType)) return Ok(JsonView(false, MsgTips.Port));
  6047. RefAsync<int> total = 0;
  6048. var data = await _sqlSugar.Queryable<Res_BasicInsuranceCost>()
  6049. .LeftJoin<Sys_Users>((bic, u) => bic.CreateUserId == u.Id)
  6050. .Where((bic, u) => bic.IsDel == 0)
  6051. .WhereIF(!string.IsNullOrEmpty(dto.Search), (bic, u) => bic.CountryName.Contains(dto.Search))
  6052. .OrderByDescending((bic, u) => bic.Id)
  6053. .Select((bic, u) => new
  6054. {
  6055. bic.Id,
  6056. bic.IsSchengen,
  6057. bic.CountryName,
  6058. bic.Cost,
  6059. bic.Remark,
  6060. CreateUserName = u.CnName,
  6061. bic.CreateTime
  6062. })
  6063. .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
  6064. return Ok(JsonView(data, total));
  6065. }
  6066. /// <summary>
  6067. /// 保险国家基础费用
  6068. /// 操作(添加 Or 编辑)
  6069. /// </summary>
  6070. /// <param name="dto"></param>
  6071. /// <returns></returns>
  6072. [HttpPost]
  6073. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6074. public async Task<IActionResult> InsuranceCostOp(InsuranceCostOpDto dto)
  6075. {
  6076. var result = new JsonView() { Code = 400, Msg = "操作失败" };
  6077. var userId = dto.CurrUserId;
  6078. if (!_portIds.Contains(dto.PortType)) return Ok(JsonView(false, MsgTips.Port));
  6079. if (userId < 1) return Ok(JsonView(false, MsgTips.UserId));
  6080. var countryName = dto.CountryName.Trim();
  6081. if (string.IsNullOrEmpty(countryName)) return Ok(JsonView(false, $"国家名称不能为空!"));
  6082. var info = _mapper.Map<Res_BasicInsuranceCost>(dto);
  6083. info.CreateUserId = dto.CurrUserId;
  6084. info.CountryName = countryName;
  6085. if (dto.Id < 1) //添加
  6086. {
  6087. var addInfo = await _insuranceCostRep.Query(x => x.CountryName.Equals(countryName)).FirstAsync();
  6088. if (addInfo != null) return Ok(JsonView(false, $"该国家信息已存在,不可添加!"));
  6089. var add = await _insuranceCostRep.AddAsync(info);
  6090. if (add < 1) return Ok(JsonView(false, "添加失败!"));
  6091. }
  6092. else //修改
  6093. {
  6094. var upd = await _insuranceCostRep.UpdateAsync(x => x.Id == dto.Id, x => new Res_BasicInsuranceCost
  6095. {
  6096. IsSchengen = dto.IsSchengen,
  6097. CountryName = dto.CountryName,
  6098. Cost = dto.Cost,
  6099. Remark = dto.Remark
  6100. });
  6101. if (!upd) return Ok(JsonView(false, "修改失败!"));
  6102. }
  6103. return Ok(JsonView(true));
  6104. }
  6105. /// <summary>
  6106. /// 保险国家基础费用
  6107. /// 删除
  6108. /// </summary>
  6109. /// <param name="dto"></param>
  6110. /// <returns></returns>
  6111. [HttpPost]
  6112. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6113. public async Task<IActionResult> InsuranceCostSoftDel(InsuranceCostSoftDelDto dto)
  6114. {
  6115. int userId = dto.CurrUserId, id = dto.Id;
  6116. if (!_portIds.Contains(dto.PortType)) return Ok(JsonView(false, MsgTips.Port));
  6117. if (userId < 1) return Ok(JsonView(false, MsgTips.UserId));
  6118. if (id < 1) return Ok(JsonView(false, MsgTips.Id));
  6119. var del = await _insuranceCostRep.SoftDeleteAsync(x => x.Id == id, userId);
  6120. if (!del) return Ok(JsonView(false));
  6121. return Ok(JsonView(true));
  6122. }
  6123. #endregion
  6124. #region 世运会成本预算明细
  6125. /// <summary>
  6126. /// 世运会成本预算明细
  6127. /// Info
  6128. /// </summary>
  6129. /// <param name="id"></param>
  6130. /// <returns></returns>
  6131. [HttpGet("{id}")]
  6132. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6133. public async Task<IActionResult> GamesBudgetMasterInfo([Required(ErrorMessage = "数据编号不能为空!")] int id)
  6134. {
  6135. return Ok(await _gamesBudgetMasterRep.InfoAsync(id));
  6136. }
  6137. /// <summary>
  6138. /// 世运会成本预算明细
  6139. /// List
  6140. /// </summary>
  6141. /// <param name="dto"></param>
  6142. /// <returns></returns>
  6143. [HttpPost]
  6144. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6145. public async Task<IActionResult> GamesBudgetMasterList(GamesBudgetMasterListDto dto)
  6146. {
  6147. return Ok(await _gamesBudgetMasterRep.ListAsync(dto));
  6148. }
  6149. /// <summary>
  6150. /// 世运会成本预算明细
  6151. /// OP(Add/Edit)
  6152. /// </summary>
  6153. /// <param name="dto"></param>
  6154. /// <returns></returns>
  6155. [HttpPost]
  6156. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6157. public async Task<IActionResult> GamesBudgetMasterOP(GamesBudgetMasterOPDto dto)
  6158. {
  6159. if (dto.Id > 0)
  6160. {
  6161. //修改
  6162. var editDto = _mapper.Map<GamesBudgetMasterEditDto>(dto);
  6163. return Ok(await _gamesBudgetMasterRep.EditAsync(editDto));
  6164. }
  6165. else if (dto.Id < 1)
  6166. {
  6167. //添加
  6168. var addDto = _mapper.Map<GamesBudgetMasterAddDto>(dto);
  6169. return Ok(await _gamesBudgetMasterRep.AddAsync(addDto));
  6170. }
  6171. return Ok(JsonView(false));
  6172. }
  6173. /// <summary>
  6174. /// 世运会成本预算明细
  6175. /// 删除
  6176. /// </summary>
  6177. /// <param name="dto"></param>
  6178. /// <returns></returns>
  6179. [HttpPost]
  6180. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6181. public async Task<IActionResult> GamesBudgetMasterDel(GamesBudgetMasterDelDto dto)
  6182. {
  6183. return Ok(await _gamesBudgetMasterRep.DelAsync(dto));
  6184. }
  6185. #endregion
  6186. #region 境外用车
  6187. /// <summary>
  6188. /// 境外用车
  6189. /// Init
  6190. /// </summary>
  6191. /// <returns></returns>
  6192. [HttpGet()]
  6193. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6194. public async Task<IActionResult> OverseaVehicleInitAsync()
  6195. {
  6196. return Ok(await _overseaVehicleRep.InitAsync());
  6197. }
  6198. /// <summary>
  6199. /// 境外用车
  6200. /// Info
  6201. /// </summary>
  6202. /// <param name="id"></param>
  6203. /// <returns></returns>
  6204. [HttpGet("{id}")]
  6205. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6206. public async Task<IActionResult> OverseaVehicleInfoAsync([Required(ErrorMessage = "数据编号不能为空!")] int id)
  6207. {
  6208. return Ok(await _overseaVehicleRep.InfoAsync(id));
  6209. }
  6210. /// <summary>
  6211. /// 境外用车
  6212. /// List
  6213. /// </summary>
  6214. /// <param name="dto"></param>
  6215. /// <returns></returns>
  6216. [HttpPost]
  6217. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6218. public async Task<IActionResult> OverseaVehicleListAsync(OverseaVehicleListDto dto)
  6219. {
  6220. return Ok(await _overseaVehicleRep.ListAsync(dto));
  6221. }
  6222. /// <summary>
  6223. /// 境外用车
  6224. /// OP(Add/Edit)
  6225. /// </summary>
  6226. /// <param name="dto"></param>
  6227. /// <returns></returns>
  6228. [HttpPost]
  6229. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6230. public async Task<IActionResult> OverseaVehicleAddOrEditAsync(OverseaVehicleAddOrEditDto dto)
  6231. {
  6232. if (dto.Id > 0)
  6233. {
  6234. //修改
  6235. return Ok(await _overseaVehicleRep.EditAsync(dto));
  6236. }
  6237. else if (dto.Id < 1)
  6238. {
  6239. //添加
  6240. return Ok(await _overseaVehicleRep.AddAsync(dto));
  6241. }
  6242. return Ok(JsonView(false));
  6243. }
  6244. /// <summary>
  6245. /// 境外用车
  6246. /// 删除
  6247. /// </summary>
  6248. /// <param name="dto"></param>
  6249. /// <returns></returns>
  6250. [HttpPost]
  6251. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6252. public async Task<IActionResult> OverseaVehicleDelAsync(OverseaVehicleDelDto dto)
  6253. {
  6254. return Ok(await _overseaVehicleRep.DelAsync(dto));
  6255. }
  6256. #endregion
  6257. #region 物料成本
  6258. /// <summary>
  6259. /// 物料成本列表查询
  6260. /// </summary>
  6261. /// <param name="dto"></param>
  6262. /// <returns></returns>
  6263. [HttpPost]
  6264. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6265. public async Task<IActionResult> MaterialCostList(QueryMaterialCostDto dto)
  6266. {
  6267. var data = await _materialCostRep.GetListAsync(dto);
  6268. return Ok(JsonView(true, "查询成功", data));
  6269. }
  6270. /// <summary>
  6271. /// 物料成本详情
  6272. /// </summary>
  6273. /// <param name="id"></param>
  6274. /// <returns></returns>
  6275. [HttpGet]
  6276. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6277. public async Task<IActionResult> MaterialCostInfo(int id)
  6278. {
  6279. var data = await _materialCostRep.GetDetailAsync(id);
  6280. return Ok(JsonView(true, "查询成功", data));
  6281. }
  6282. /// <summary>
  6283. /// 物料成本添加/修改
  6284. /// </summary>
  6285. /// <param name="dto"></param>
  6286. /// <returns></returns>
  6287. [HttpPost]
  6288. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6289. public async Task<IActionResult> MaterialCostAddOrEdit(UpMaterialCostDto dto)
  6290. {
  6291. if (dto.Id > 0)
  6292. {
  6293. // 修改
  6294. var entity = _mapper.Map<Res_MaterialCost>(dto);
  6295. var result = await _materialCostRep.UpdateAsync(s => s.Id == dto.Id, it => new Res_MaterialCost()
  6296. {
  6297. TypeId = entity.TypeId,
  6298. Name = entity.Name,
  6299. Price = entity.Price,
  6300. Number = entity.Number,
  6301. Unit = entity.Unit,
  6302. SetDataId = entity.SetDataId,
  6303. CityId = entity.CityId,
  6304. Remark = entity.Remark
  6305. });
  6306. return Ok(JsonView(result, result ? "修改成功" : "修改失败"));
  6307. }
  6308. else
  6309. {
  6310. // 添加
  6311. var entity = _mapper.Map<Res_MaterialCost>(dto);
  6312. entity.CreateTime = DateTime.Now;
  6313. var result = await _materialCostRep.AddAsync(entity);
  6314. return Ok(JsonView(result > 0, result > 0 ? "添加成功" : "添加失败"));
  6315. }
  6316. }
  6317. /// <summary>
  6318. /// 物料成本删除
  6319. /// </summary>
  6320. /// <param name="dto"></param>
  6321. /// <returns></returns>
  6322. [HttpPost]
  6323. [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
  6324. public async Task<IActionResult> MaterialCostDel(DelBaseDto dto)
  6325. {
  6326. var result = await _materialCostRep.SoftDeleteAsync(dto.Id.ToString());
  6327. return Ok(JsonView(result, result ? "删除成功" : "删除失败"));
  6328. }
  6329. #endregion
  6330. }
  6331. }