app.html 349 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>FashionCraft - 服装DIY设计</title>
  7. <style>
  8. * {
  9. box-sizing: border-box;
  10. margin: 0;
  11. padding: 0;
  12. }
  13. body {
  14. font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
  15. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  16. min-height: 100vh;
  17. color: #333;
  18. }
  19. /* 登录注册欢迎页面样式 */
  20. .auth-screen {
  21. position: fixed;
  22. top: 0;
  23. left: 0;
  24. width: 100%;
  25. height: 100vh;
  26. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  27. z-index: 9999;
  28. display: flex;
  29. justify-content: center;
  30. align-items: center;
  31. transition: all 0.5s ease;
  32. }
  33. .auth-container {
  34. max-width: 414px;
  35. width: 90%;
  36. background: rgba(255, 255, 255, 0.95);
  37. backdrop-filter: blur(20px);
  38. border-radius: 25px;
  39. box-shadow: 0 25px 60px rgba(0, 0, 0, 0.3);
  40. overflow: hidden;
  41. animation: slideUp 0.8s ease-out;
  42. }
  43. @keyframes slideUp {
  44. from {
  45. opacity: 0;
  46. transform: translateY(50px);
  47. }
  48. to {
  49. opacity: 1;
  50. transform: translateY(0);
  51. }
  52. }
  53. .auth-header {
  54. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  55. padding: 40px 30px 30px;
  56. text-align: center;
  57. color: white;
  58. position: relative;
  59. overflow: hidden;
  60. }
  61. .auth-header::before {
  62. content: '';
  63. position: absolute;
  64. top: -50%;
  65. left: -50%;
  66. width: 200%;
  67. height: 200%;
  68. background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="authGrain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="20" cy="20" r="1" fill="white" opacity="0.1"/><circle cx="80" cy="80" r="1" fill="white" opacity="0.1"/><circle cx="40" cy="60" r="1" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23authGrain)"/></svg>');
  69. animation: float 20s infinite linear;
  70. }
  71. .brand-logo {
  72. position: relative;
  73. z-index: 2;
  74. }
  75. .logo-icon {
  76. font-size: 48px;
  77. margin-bottom: 10px;
  78. animation: sparkle 2s infinite ease-in-out;
  79. }
  80. .brand-logo h1 {
  81. font-size: 32px;
  82. font-weight: 700;
  83. margin-bottom: 5px;
  84. text-shadow: 0 2px 4px rgba(0,0,0,0.3);
  85. }
  86. .brand-logo p {
  87. opacity: 0.9;
  88. font-size: 16px;
  89. }
  90. .auth-content {
  91. padding: 30px;
  92. }
  93. .welcome-message {
  94. text-align: center;
  95. margin-bottom: 30px;
  96. }
  97. .welcome-message h2 {
  98. font-size: 24px;
  99. font-weight: 600;
  100. color: #333;
  101. margin-bottom: 8px;
  102. }
  103. .welcome-message p {
  104. color: #666;
  105. font-size: 16px;
  106. }
  107. .auth-actions {
  108. margin-bottom: 30px;
  109. }
  110. .auth-btn {
  111. width: 100%;
  112. padding: 16px;
  113. border: none;
  114. border-radius: 12px;
  115. font-size: 16px;
  116. font-weight: 600;
  117. cursor: pointer;
  118. transition: all 0.3s ease;
  119. margin-bottom: 12px;
  120. display: flex;
  121. align-items: center;
  122. justify-content: center;
  123. gap: 8px;
  124. }
  125. .auth-btn.primary {
  126. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  127. color: white;
  128. box-shadow: 0 4px 15px rgba(255, 107, 107, 0.4);
  129. }
  130. .auth-btn.primary:hover {
  131. transform: translateY(-2px);
  132. box-shadow: 0 8px 25px rgba(255, 107, 107, 0.6);
  133. }
  134. .auth-btn.secondary {
  135. background: #f8f9fa;
  136. color: #333;
  137. border: 2px solid #e9ecef;
  138. }
  139. .auth-btn.secondary:hover {
  140. background: #e9ecef;
  141. transform: translateY(-1px);
  142. }
  143. .btn-icon {
  144. font-size: 18px;
  145. }
  146. .auth-features {
  147. margin-bottom: 20px;
  148. }
  149. .feature-item {
  150. display: flex;
  151. align-items: center;
  152. gap: 15px;
  153. padding: 15px 0;
  154. border-bottom: 1px solid #f0f0f0;
  155. }
  156. .feature-item:last-child {
  157. border-bottom: none;
  158. }
  159. .feature-icon {
  160. width: 45px;
  161. height: 45px;
  162. background: linear-gradient(45deg, #667eea, #764ba2);
  163. border-radius: 12px;
  164. display: flex;
  165. align-items: center;
  166. justify-content: center;
  167. font-size: 20px;
  168. color: white;
  169. }
  170. .feature-text {
  171. flex: 1;
  172. }
  173. .feature-title {
  174. font-size: 16px;
  175. font-weight: 600;
  176. color: #333;
  177. margin-bottom: 2px;
  178. }
  179. .feature-desc {
  180. font-size: 14px;
  181. color: #666;
  182. }
  183. .auth-footer {
  184. background: #f8f9fa;
  185. padding: 20px 30px;
  186. text-align: center;
  187. border-top: 1px solid #e9ecef;
  188. }
  189. .version-info {
  190. font-size: 14px;
  191. color: #666;
  192. margin-bottom: 5px;
  193. }
  194. .copyright {
  195. font-size: 12px;
  196. color: #999;
  197. }
  198. /* 容器样式 */
  199. .app-container {
  200. max-width: 414px;
  201. margin: 0 auto;
  202. background: #fff;
  203. min-height: 100vh;
  204. box-shadow: 0 0 30px rgba(0,0,0,0.3);
  205. overflow: hidden;
  206. position: relative;
  207. }
  208. /* 头部导航 */
  209. .header {
  210. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  211. padding: 20px 20px 15px;
  212. color: white;
  213. position: relative;
  214. overflow: hidden;
  215. }
  216. .header::before {
  217. content: '';
  218. position: absolute;
  219. top: -50%;
  220. left: -50%;
  221. width: 200%;
  222. height: 200%;
  223. background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="20" cy="20" r="1" fill="white" opacity="0.1"/><circle cx="80" cy="80" r="1" fill="white" opacity="0.1"/><circle cx="40" cy="60" r="1" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
  224. animation: float 20s infinite linear;
  225. }
  226. @keyframes float {
  227. 0% { transform: translate(-50%, -50%) rotate(0deg); }
  228. 100% { transform: translate(-50%, -50%) rotate(360deg); }
  229. }
  230. .header-content {
  231. position: relative;
  232. z-index: 2;
  233. }
  234. .header h1 {
  235. font-size: 28px;
  236. font-weight: 700;
  237. margin-bottom: 5px;
  238. text-shadow: 0 2px 4px rgba(0,0,0,0.3);
  239. }
  240. .header p {
  241. opacity: 0.9;
  242. font-size: 14px;
  243. }
  244. /* 主要内容区域 */
  245. .main-content {
  246. flex: 1;
  247. overflow-y: auto;
  248. padding-bottom: 80px;
  249. }
  250. /* 轮播区域 */
  251. .banner-section {
  252. position: relative;
  253. height: 200px;
  254. overflow: hidden;
  255. margin: 20px;
  256. border-radius: 20px;
  257. box-shadow: 0 10px 30px rgba(0,0,0,0.2);
  258. }
  259. .banner-slider {
  260. display: flex;
  261. transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  262. height: 100%;
  263. }
  264. .banner-slide {
  265. min-width: 100%;
  266. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  267. display: flex;
  268. align-items: center;
  269. justify-content: center;
  270. color: white;
  271. font-size: 18px;
  272. font-weight: 600;
  273. position: relative;
  274. overflow: hidden;
  275. cursor: pointer;
  276. transition: transform 0.3s ease;
  277. }
  278. .banner-slide:hover {
  279. transform: scale(0.98);
  280. }
  281. .banner-slide::before {
  282. content: '';
  283. position: absolute;
  284. top: 0;
  285. left: 0;
  286. right: 0;
  287. bottom: 0;
  288. background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><defs><linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:rgba(255,255,255,0.1)"/><stop offset="100%" style="stop-color:rgba(255,255,255,0)"/></linearGradient></defs><polygon points="0,0 100,0 0,100" fill="url(%23grad)"/></svg>');
  289. pointer-events: none;
  290. }
  291. .banner-indicators {
  292. position: absolute;
  293. bottom: 15px;
  294. left: 50%;
  295. transform: translateX(-50%);
  296. display: flex;
  297. gap: 8px;
  298. }
  299. .indicator {
  300. width: 8px;
  301. height: 8px;
  302. border-radius: 50%;
  303. background: rgba(255,255,255,0.5);
  304. cursor: pointer;
  305. transition: all 0.3s ease;
  306. }
  307. .indicator.active {
  308. background: white;
  309. transform: scale(1.2);
  310. }
  311. /* 快速设计入口 */
  312. .quick-design {
  313. margin: 20px;
  314. padding: 25px;
  315. background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 50%, #fecfef 100%);
  316. border-radius: 20px;
  317. text-align: center;
  318. box-shadow: 0 8px 25px rgba(255, 154, 158, 0.4);
  319. position: relative;
  320. overflow: hidden;
  321. cursor: pointer;
  322. transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  323. }
  324. .quick-design:hover {
  325. transform: translateY(-5px);
  326. box-shadow: 0 15px 35px rgba(255, 154, 158, 0.6);
  327. }
  328. .quick-design::before {
  329. content: '✨';
  330. position: absolute;
  331. top: 15px;
  332. right: 20px;
  333. font-size: 24px;
  334. animation: sparkle 2s infinite;
  335. }
  336. @keyframes sparkle {
  337. 0%, 100% { transform: scale(1) rotate(0deg); opacity: 1; }
  338. 50% { transform: scale(1.2) rotate(180deg); opacity: 0.8; }
  339. }
  340. .quick-design h2 {
  341. font-size: 22px;
  342. color: #fff;
  343. margin-bottom: 8px;
  344. text-shadow: 0 2px 4px rgba(0,0,0,0.2);
  345. }
  346. .quick-design p {
  347. color: rgba(255,255,255,0.9);
  348. font-size: 14px;
  349. }
  350. /* 热门作品区 */
  351. .popular-works {
  352. margin: 20px;
  353. }
  354. .section-title {
  355. font-size: 20px;
  356. font-weight: 700;
  357. margin-bottom: 15px;
  358. color: #333;
  359. position: relative;
  360. padding-left: 15px;
  361. }
  362. .section-title::before {
  363. content: '';
  364. position: absolute;
  365. left: 0;
  366. top: 50%;
  367. transform: translateY(-50%);
  368. width: 4px;
  369. height: 20px;
  370. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  371. border-radius: 2px;
  372. }
  373. .works-grid {
  374. display: grid;
  375. grid-template-columns: repeat(2, 1fr);
  376. gap: 15px;
  377. }
  378. .work-item {
  379. background: #fff;
  380. border-radius: 15px;
  381. overflow: hidden;
  382. box-shadow: 0 5px 20px rgba(0,0,0,0.1);
  383. transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  384. cursor: pointer;
  385. }
  386. .work-item:hover {
  387. transform: translateY(-8px);
  388. box-shadow: 0 15px 40px rgba(0,0,0,0.2);
  389. }
  390. .work-image {
  391. height: 120px;
  392. background: linear-gradient(45deg, #a8edea 0%, #fed6e3 100%);
  393. position: relative;
  394. display: flex;
  395. align-items: center;
  396. justify-content: center;
  397. font-size: 36px;
  398. }
  399. .work-info {
  400. padding: 12px;
  401. }
  402. .work-title {
  403. font-size: 14px;
  404. font-weight: 600;
  405. margin-bottom: 4px;
  406. color: #333;
  407. }
  408. .work-stats {
  409. display: flex;
  410. justify-content: space-between;
  411. font-size: 12px;
  412. color: #666;
  413. }
  414. /* AI推荐引擎样式 */
  415. .ai-recommend-engine {
  416. margin: 20px;
  417. }
  418. .ai-engine-card {
  419. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  420. border-radius: 20px;
  421. padding: 25px;
  422. color: white;
  423. box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3);
  424. }
  425. .ai-engine-header {
  426. display: flex;
  427. justify-content: space-between;
  428. align-items: center;
  429. margin-bottom: 20px;
  430. }
  431. .ai-brand {
  432. display: flex;
  433. align-items: center;
  434. gap: 12px;
  435. }
  436. .ai-logo {
  437. font-size: 32px;
  438. animation: pulse 2s infinite;
  439. }
  440. .ai-brand-text h3 {
  441. font-size: 20px;
  442. margin: 0 0 4px 0;
  443. font-weight: 700;
  444. }
  445. .ai-brand-text p {
  446. font-size: 14px;
  447. opacity: 0.9;
  448. margin: 0;
  449. }
  450. .ai-status {
  451. display: flex;
  452. align-items: center;
  453. gap: 6px;
  454. font-size: 12px;
  455. opacity: 0.9;
  456. }
  457. .status-dot {
  458. width: 8px;
  459. height: 8px;
  460. background: #4ade80;
  461. border-radius: 50%;
  462. animation: pulse 2s infinite;
  463. }
  464. .ai-quick-actions {
  465. display: grid;
  466. grid-template-columns: repeat(2, 1fr);
  467. gap: 12px;
  468. margin-bottom: 20px;
  469. }
  470. .quick-action {
  471. background: rgba(255,255,255,0.15);
  472. border-radius: 15px;
  473. padding: 15px 12px;
  474. display: flex;
  475. align-items: center;
  476. gap: 10px;
  477. cursor: pointer;
  478. transition: all 0.3s ease;
  479. backdrop-filter: blur(10px);
  480. min-height: 50px;
  481. text-align: left;
  482. }
  483. .quick-action:hover {
  484. background: rgba(255,255,255,0.25);
  485. transform: translateY(-2px);
  486. box-shadow: 0 5px 15px rgba(255,255,255,0.1);
  487. }
  488. .action-icon {
  489. font-size: 20px;
  490. }
  491. .action-text {
  492. font-size: 14px;
  493. font-weight: 500;
  494. }
  495. /* AI悬浮球样式 */
  496. .ai-floating-ball {
  497. position: fixed;
  498. bottom: 90px;
  499. right: 20px;
  500. width: 60px;
  501. height: 60px;
  502. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  503. border-radius: 50%;
  504. display: flex;
  505. align-items: center;
  506. justify-content: center;
  507. cursor: pointer;
  508. z-index: 999;
  509. box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
  510. transition: all 0.3s ease;
  511. }
  512. .ai-floating-ball:hover {
  513. transform: scale(1.1);
  514. box-shadow: 0 12px 35px rgba(102, 126, 234, 0.6);
  515. }
  516. .floating-ball-icon {
  517. font-size: 24px;
  518. color: white;
  519. z-index: 2;
  520. position: relative;
  521. }
  522. .breathing-ring {
  523. position: absolute;
  524. top: -3px;
  525. left: -3px;
  526. right: -3px;
  527. bottom: -3px;
  528. border: 2px solid rgba(102, 126, 234, 0.6);
  529. border-radius: 50%;
  530. animation: breathing 2s ease-in-out infinite;
  531. }
  532. @keyframes breathing {
  533. 0%, 100% {
  534. transform: scale(1);
  535. opacity: 1;
  536. }
  537. 50% {
  538. transform: scale(1.1);
  539. opacity: 0.7;
  540. }
  541. }
  542. /* AI全屏对话界面样式 */
  543. .ai-chat-modal {
  544. position: fixed;
  545. top: 0;
  546. left: 0;
  547. width: 100%;
  548. height: 100%;
  549. background: rgba(0,0,0,0.95);
  550. backdrop-filter: blur(10px);
  551. z-index: 2000;
  552. display: flex;
  553. align-items: center;
  554. justify-content: center;
  555. animation: fadeIn 0.3s ease;
  556. }
  557. .ai-chat-container {
  558. width: 100%;
  559. max-width: 414px;
  560. height: 100%;
  561. background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
  562. display: flex;
  563. flex-direction: column;
  564. position: relative;
  565. }
  566. .ai-chat-header {
  567. padding: 20px;
  568. display: flex;
  569. align-items: center;
  570. gap: 15px;
  571. border-bottom: 1px solid rgba(255,255,255,0.2);
  572. background: rgba(255,255,255,0.1);
  573. backdrop-filter: blur(10px);
  574. }
  575. .ai-chat-avatar {
  576. position: relative;
  577. width: 50px;
  578. height: 50px;
  579. background: rgba(255,255,255,0.2);
  580. border-radius: 50%;
  581. display: flex;
  582. align-items: center;
  583. justify-content: center;
  584. }
  585. .avatar-icon {
  586. font-size: 24px;
  587. color: white;
  588. }
  589. .avatar-status {
  590. position: absolute;
  591. bottom: 2px;
  592. right: 2px;
  593. width: 12px;
  594. height: 12px;
  595. background: #4ade80;
  596. border: 2px solid white;
  597. border-radius: 50%;
  598. }
  599. .ai-chat-info {
  600. flex: 1;
  601. color: white;
  602. }
  603. .ai-chat-info h3 {
  604. font-size: 18px;
  605. margin: 0 0 4px 0;
  606. font-weight: 600;
  607. }
  608. .ai-chat-info p {
  609. font-size: 14px;
  610. margin: 0;
  611. opacity: 0.9;
  612. }
  613. .ai-chat-close {
  614. width: 40px;
  615. height: 40px;
  616. background: rgba(255,255,255,0.2);
  617. border: none;
  618. border-radius: 50%;
  619. color: white;
  620. font-size: 18px;
  621. cursor: pointer;
  622. transition: all 0.3s ease;
  623. }
  624. .ai-chat-close:hover {
  625. background: rgba(255,255,255,0.3);
  626. }
  627. .ai-chat-messages {
  628. flex: 1;
  629. overflow-y: auto;
  630. padding: 20px;
  631. display: flex;
  632. flex-direction: column;
  633. gap: 15px;
  634. }
  635. .ai-message {
  636. display: flex;
  637. align-items: flex-start;
  638. gap: 12px;
  639. }
  640. .user-message {
  641. display: flex;
  642. align-items: flex-start;
  643. gap: 12px;
  644. flex-direction: row-reverse;
  645. }
  646. .message-avatar {
  647. width: 35px;
  648. height: 35px;
  649. background: rgba(255,255,255,0.2);
  650. border-radius: 50%;
  651. display: flex;
  652. align-items: center;
  653. justify-content: center;
  654. font-size: 16px;
  655. flex-shrink: 0;
  656. }
  657. .user-message .message-avatar {
  658. background: rgba(255,255,255,0.9);
  659. }
  660. .message-content {
  661. flex: 1;
  662. max-width: 80%;
  663. }
  664. .message-text {
  665. background: rgba(255,255,255,0.15);
  666. padding: 14px 18px;
  667. border-radius: 20px;
  668. color: white;
  669. font-size: 14px;
  670. line-height: 1.5;
  671. backdrop-filter: blur(10px);
  672. box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  673. border: 1px solid rgba(255,255,255,0.1);
  674. }
  675. .user-message .message-text {
  676. background: rgba(255,255,255,0.95);
  677. color: #333;
  678. box-shadow: 0 3px 10px rgba(0,0,0,0.1);
  679. border: 1px solid rgba(255,255,255,0.3);
  680. }
  681. /* AI消息特殊样式增强 */
  682. .ai-message .message-text.ai-formatted {
  683. background: linear-gradient(135deg, rgba(255,255,255,0.18), rgba(255,255,255,0.12));
  684. border: 1px solid rgba(255,255,255,0.15);
  685. }
  686. .message-time {
  687. font-size: 11px;
  688. color: rgba(255,255,255,0.7);
  689. margin-top: 4px;
  690. padding-left: 16px;
  691. }
  692. .user-message .message-time {
  693. color: rgba(0,0,0,0.5);
  694. text-align: right;
  695. padding-left: 0;
  696. padding-right: 16px;
  697. }
  698. .ai-quick-commands {
  699. padding: 15px 20px;
  700. display: flex;
  701. gap: 10px;
  702. overflow-x: auto;
  703. background: rgba(255,255,255,0.05);
  704. }
  705. .quick-command {
  706. min-width: 120px;
  707. background: rgba(255,255,255,0.1);
  708. border-radius: 20px;
  709. padding: 10px 15px;
  710. display: flex;
  711. align-items: center;
  712. gap: 8px;
  713. cursor: pointer;
  714. transition: all 0.3s ease;
  715. color: white;
  716. font-size: 13px;
  717. }
  718. .quick-command:hover {
  719. background: rgba(255,255,255,0.2);
  720. transform: translateY(-2px);
  721. }
  722. .command-icon {
  723. font-size: 16px;
  724. }
  725. .ai-chat-input-area {
  726. padding: 20px;
  727. background: rgba(255,255,255,0.1);
  728. backdrop-filter: blur(10px);
  729. }
  730. .input-toolbar {
  731. display: flex;
  732. gap: 10px;
  733. margin-bottom: 12px;
  734. }
  735. .input-tool {
  736. color: white;
  737. cursor: pointer;
  738. transition: all 0.3s ease;
  739. display: flex;
  740. align-items: center;
  741. justify-content: center;
  742. padding: 2px;
  743. outline: none;
  744. background: none;
  745. border: none;
  746. }
  747. .input-tool:hover {
  748. transform: scale(1.1);
  749. }
  750. .input-tool:focus {
  751. outline: none;
  752. }
  753. .tool-icon {
  754. font-size: 14px;
  755. display: flex;
  756. align-items: center;
  757. justify-content: center;
  758. border: none;
  759. }
  760. .input-container {
  761. display: flex;
  762. gap: 10px;
  763. align-items: center;
  764. }
  765. .input-container input {
  766. flex: 1;
  767. background: rgba(255,255,255,0.9);
  768. border: none;
  769. border-radius: 25px;
  770. padding: 12px 20px;
  771. font-size: 14px;
  772. outline: none;
  773. color: #333;
  774. }
  775. .input-container input::placeholder {
  776. color: #999;
  777. }
  778. .send-button {
  779. width: 45px;
  780. height: 45px;
  781. background: linear-gradient(135deg, #ff6b6b, #ffa726);
  782. border: none;
  783. border-radius: 50%;
  784. color: white;
  785. cursor: pointer;
  786. transition: all 0.3s ease;
  787. display: flex;
  788. align-items: center;
  789. justify-content: center;
  790. }
  791. .send-button:hover {
  792. transform: scale(1.05);
  793. box-shadow: 0 5px 15px rgba(255, 107, 107, 0.4);
  794. }
  795. .send-icon {
  796. font-size: 18px;
  797. }
  798. /* 加载消息样式 */
  799. .loading-message .message-text {
  800. background: rgba(255,255,255,0.25);
  801. color: rgba(255,255,255,0.9);
  802. font-style: italic;
  803. }
  804. .loading-dots {
  805. opacity: 0.8;
  806. }
  807. .dots {
  808. color: #ffa726;
  809. font-weight: bold;
  810. }
  811. /* AI消息格式化样式 */
  812. .ai-formatted {
  813. line-height: 1.6;
  814. }
  815. .ai-bold {
  816. font-weight: 600;
  817. color: #ffffff;
  818. text-shadow: 0 1px 2px rgba(0,0,0,0.3);
  819. }
  820. .ai-italic {
  821. font-style: italic;
  822. color: rgba(255,255,255,0.9);
  823. }
  824. .ai-list-item {
  825. margin: 8px 0;
  826. padding: 6px 12px;
  827. display: flex;
  828. align-items: flex-start;
  829. gap: 8px;
  830. background: rgba(255,255,255,0.05);
  831. border-radius: 8px;
  832. transition: all 0.3s ease;
  833. }
  834. .ai-list-item:hover {
  835. background: rgba(255,255,255,0.1);
  836. transform: translateX(5px);
  837. }
  838. .ai-list-number {
  839. color: #ffa726;
  840. font-weight: 600;
  841. min-width: 20px;
  842. text-align: right;
  843. text-shadow: 0 1px 2px rgba(0,0,0,0.3);
  844. }
  845. .ai-bullet {
  846. color: #ff6b6b;
  847. font-weight: bold;
  848. min-width: 16px;
  849. text-shadow: 0 1px 2px rgba(0,0,0,0.3);
  850. }
  851. .ai-list-content {
  852. flex: 1;
  853. line-height: 1.4;
  854. }
  855. .ai-quote {
  856. background: rgba(255,255,255,0.1);
  857. border-left: 3px solid #ffa726;
  858. padding: 12px 16px;
  859. margin: 12px 0;
  860. border-radius: 0 8px 8px 0;
  861. font-style: italic;
  862. position: relative;
  863. box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  864. }
  865. .ai-quote-icon {
  866. margin-right: 8px;
  867. animation: ideaPulse 2s ease-in-out infinite;
  868. }
  869. .ai-divider {
  870. width: 100%;
  871. height: 2px;
  872. background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
  873. margin: 16px 0;
  874. border-radius: 1px;
  875. }
  876. .ai-color-tag {
  877. display: inline-block;
  878. margin: 0 2px;
  879. box-shadow: 0 2px 4px rgba(0,0,0,0.2);
  880. vertical-align: middle;
  881. transition: transform 0.2s ease;
  882. }
  883. .ai-color-tag:hover {
  884. transform: scale(1.1);
  885. }
  886. /* 特殊标签样式 */
  887. .ai-tag {
  888. display: inline-block;
  889. padding: 2px 8px;
  890. border-radius: 12px;
  891. font-size: 11px;
  892. font-weight: 600;
  893. margin: 0 4px;
  894. text-transform: uppercase;
  895. letter-spacing: 0.5px;
  896. box-shadow: 0 2px 4px rgba(0,0,0,0.2);
  897. }
  898. .ai-tag-important {
  899. background: linear-gradient(45deg, #ff6b6b, #ff5252);
  900. color: white;
  901. }
  902. .ai-tag-suggestion {
  903. background: linear-gradient(45deg, #4ecdc4, #44a08d);
  904. color: white;
  905. }
  906. .ai-tag-tip {
  907. background: linear-gradient(45deg, #ffa726, #ff9800);
  908. color: white;
  909. }
  910. /* 段落间距 */
  911. .ai-paragraph-break {
  912. height: 12px;
  913. }
  914. /* 表情增强效果 */
  915. .ai-sparkle, .ai-idea, .ai-art, .ai-suit, .ai-dress, .ai-heels, .ai-makeup, .ai-bag {
  916. display: inline-block;
  917. cursor: pointer;
  918. transition: transform 0.2s ease;
  919. }
  920. .ai-sparkle:hover, .ai-idea:hover, .ai-art:hover, .ai-suit:hover,
  921. .ai-dress:hover, .ai-heels:hover, .ai-makeup:hover, .ai-bag:hover {
  922. transform: scale(1.3);
  923. }
  924. .ai-sparkle {
  925. animation: sparkleGlow 2s ease-in-out infinite;
  926. }
  927. .ai-idea {
  928. animation: ideaPulse 1.5s ease-in-out infinite;
  929. }
  930. .ai-art {
  931. animation: artSway 3s ease-in-out infinite;
  932. }
  933. .ai-suit {
  934. animation: suitBounce 2s ease-in-out infinite;
  935. }
  936. .ai-dress {
  937. animation: dressFloat 3s ease-in-out infinite;
  938. }
  939. .ai-heels {
  940. animation: heelsStep 1.8s ease-in-out infinite;
  941. }
  942. .ai-makeup {
  943. animation: makeupShine 2.5s ease-in-out infinite;
  944. }
  945. .ai-bag {
  946. animation: bagSwing 2.2s ease-in-out infinite;
  947. }
  948. @keyframes sparkleGlow {
  949. 0%, 100% {
  950. transform: scale(1) rotate(0deg);
  951. filter: brightness(1);
  952. }
  953. 50% {
  954. transform: scale(1.1) rotate(10deg);
  955. filter: brightness(1.3);
  956. }
  957. }
  958. @keyframes ideaPulse {
  959. 0%, 100% {
  960. transform: scale(1);
  961. filter: brightness(1);
  962. }
  963. 50% {
  964. transform: scale(1.2);
  965. filter: brightness(1.5);
  966. }
  967. }
  968. @keyframes artSway {
  969. 0%, 100% { transform: rotate(-5deg); }
  970. 50% { transform: rotate(5deg); }
  971. }
  972. @keyframes suitBounce {
  973. 0%, 100% { transform: translateY(0); }
  974. 50% { transform: translateY(-3px); }
  975. }
  976. @keyframes dressFloat {
  977. 0%, 100% { transform: translateY(0) rotate(-2deg); }
  978. 50% { transform: translateY(-2px) rotate(2deg); }
  979. }
  980. @keyframes heelsStep {
  981. 0%, 100% { transform: rotate(0deg); }
  982. 25% { transform: rotate(-10deg); }
  983. 75% { transform: rotate(10deg); }
  984. }
  985. @keyframes makeupShine {
  986. 0%, 100% {
  987. transform: scale(1);
  988. filter: brightness(1) hue-rotate(0deg);
  989. }
  990. 50% {
  991. transform: scale(1.1);
  992. filter: brightness(1.2) hue-rotate(20deg);
  993. }
  994. }
  995. @keyframes bagSwing {
  996. 0%, 100% { transform: rotate(-8deg); }
  997. 50% { transform: rotate(8deg); }
  998. }
  999. @keyframes avatarPulse {
  1000. 0% { transform: scale(1); }
  1001. 50% { transform: scale(1.15); }
  1002. 100% { transform: scale(1); }
  1003. }
  1004. /* 消息文本增强 */
  1005. .ai-message .message-text {
  1006. position: relative;
  1007. overflow: hidden;
  1008. }
  1009. .ai-message .message-text::before {
  1010. content: '';
  1011. position: absolute;
  1012. top: 0;
  1013. left: -100%;
  1014. width: 100%;
  1015. height: 100%;
  1016. background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1), transparent);
  1017. transition: left 0.6s ease;
  1018. }
  1019. .ai-message:hover .message-text::before {
  1020. left: 100%;
  1021. }
  1022. /* AI推荐结果页面样式 */
  1023. .ai-recommendation-modal {
  1024. position: fixed;
  1025. top: 0;
  1026. left: 0;
  1027. width: 100%;
  1028. height: 100%;
  1029. background: rgba(0,0,0,0.95);
  1030. backdrop-filter: blur(10px);
  1031. z-index: 2000;
  1032. display: flex;
  1033. align-items: center;
  1034. justify-content: center;
  1035. animation: fadeIn 0.3s ease;
  1036. }
  1037. .recommendation-container {
  1038. width: 100%;
  1039. max-width: 414px;
  1040. height: 100%;
  1041. background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
  1042. display: flex;
  1043. flex-direction: column;
  1044. overflow-y: auto;
  1045. }
  1046. .recommendation-header {
  1047. padding: 20px;
  1048. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  1049. color: white;
  1050. display: flex;
  1051. justify-content: space-between;
  1052. align-items: center;
  1053. }
  1054. .recommendation-header h2 {
  1055. font-size: 20px;
  1056. margin: 0;
  1057. font-weight: 600;
  1058. }
  1059. .close-recommendation {
  1060. width: 40px;
  1061. height: 40px;
  1062. background: rgba(255,255,255,0.2);
  1063. border: none;
  1064. border-radius: 50%;
  1065. color: white;
  1066. font-size: 18px;
  1067. cursor: pointer;
  1068. transition: all 0.3s ease;
  1069. }
  1070. .close-recommendation:hover {
  1071. background: rgba(255,255,255,0.3);
  1072. }
  1073. .recommendation-content {
  1074. flex: 1;
  1075. padding: 20px;
  1076. }
  1077. .recommendation-3d-section {
  1078. background: white;
  1079. border-radius: 20px;
  1080. padding: 20px;
  1081. margin-bottom: 20px;
  1082. box-shadow: 0 5px 20px rgba(0,0,0,0.1);
  1083. }
  1084. .recommendation-3d-viewer {
  1085. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  1086. border-radius: 15px;
  1087. height: 250px;
  1088. margin-bottom: 20px;
  1089. display: flex;
  1090. align-items: center;
  1091. justify-content: center;
  1092. position: relative;
  1093. overflow: hidden;
  1094. }
  1095. .model-3d-container {
  1096. text-align: center;
  1097. color: white;
  1098. }
  1099. .model-3d-display {
  1100. font-size: 80px;
  1101. margin-bottom: 15px;
  1102. animation: float 3s ease-in-out infinite;
  1103. }
  1104. @keyframes float {
  1105. 0%, 100% { transform: translateY(0px); }
  1106. 50% { transform: translateY(-10px); }
  1107. }
  1108. .model-controls {
  1109. display: flex;
  1110. gap: 10px;
  1111. justify-content: center;
  1112. }
  1113. .model-control {
  1114. width: 40px;
  1115. height: 40px;
  1116. background: rgba(255,255,255,0.2);
  1117. border: none;
  1118. border-radius: 50%;
  1119. color: white;
  1120. font-size: 16px;
  1121. cursor: pointer;
  1122. transition: all 0.3s ease;
  1123. }
  1124. .model-control:hover {
  1125. background: rgba(255,255,255,0.3);
  1126. transform: scale(1.05);
  1127. }
  1128. .scheme-selector h4 {
  1129. font-size: 16px;
  1130. margin-bottom: 15px;
  1131. color: #333;
  1132. }
  1133. .scheme-tabs {
  1134. display: flex;
  1135. gap: 10px;
  1136. }
  1137. .scheme-tab {
  1138. flex: 1;
  1139. padding: 10px;
  1140. background: #f8f9fa;
  1141. border-radius: 10px;
  1142. text-align: center;
  1143. cursor: pointer;
  1144. transition: all 0.3s ease;
  1145. font-size: 14px;
  1146. font-weight: 500;
  1147. }
  1148. .scheme-tab.active {
  1149. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  1150. color: white;
  1151. }
  1152. .color-theory-section {
  1153. background: white;
  1154. border-radius: 20px;
  1155. padding: 20px;
  1156. margin-bottom: 20px;
  1157. box-shadow: 0 5px 20px rgba(0,0,0,0.1);
  1158. }
  1159. .color-theory-section h4 {
  1160. font-size: 18px;
  1161. margin-bottom: 20px;
  1162. color: #333;
  1163. }
  1164. .theory-content {
  1165. display: flex;
  1166. flex-direction: column;
  1167. gap: 15px;
  1168. }
  1169. .theory-card {
  1170. display: flex;
  1171. align-items: flex-start;
  1172. gap: 15px;
  1173. padding: 15px;
  1174. background: #f8f9fa;
  1175. border-radius: 15px;
  1176. }
  1177. .theory-icon {
  1178. width: 40px;
  1179. height: 40px;
  1180. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  1181. border-radius: 50%;
  1182. display: flex;
  1183. align-items: center;
  1184. justify-content: center;
  1185. font-size: 18px;
  1186. flex-shrink: 0;
  1187. }
  1188. .theory-text h5 {
  1189. font-size: 16px;
  1190. margin: 0 0 8px 0;
  1191. color: #333;
  1192. font-weight: 600;
  1193. }
  1194. .theory-text p {
  1195. font-size: 14px;
  1196. color: #666;
  1197. margin: 0;
  1198. line-height: 1.5;
  1199. }
  1200. .recommendation-actions {
  1201. display: flex;
  1202. gap: 12px;
  1203. margin-top: 20px;
  1204. }
  1205. .action-btn {
  1206. flex: 1;
  1207. padding: 15px;
  1208. border: none;
  1209. border-radius: 15px;
  1210. font-size: 14px;
  1211. font-weight: 600;
  1212. cursor: pointer;
  1213. transition: all 0.3s ease;
  1214. display: flex;
  1215. align-items: center;
  1216. justify-content: center;
  1217. gap: 8px;
  1218. }
  1219. .action-btn.primary {
  1220. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  1221. color: white;
  1222. }
  1223. .action-btn.secondary {
  1224. background: #f8f9fa;
  1225. color: #666;
  1226. border: 1px solid #e9ecef;
  1227. }
  1228. .action-btn:hover {
  1229. transform: translateY(-2px);
  1230. box-shadow: 0 5px 15px rgba(0,0,0,0.1);
  1231. }
  1232. .btn-icon {
  1233. font-size: 16px;
  1234. }
  1235. /* 底部导航 */
  1236. .bottom-nav {
  1237. position: fixed;
  1238. bottom: 0;
  1239. left: 50%;
  1240. transform: translateX(-50%);
  1241. width: 414px;
  1242. max-width: 100%;
  1243. background: rgba(255,255,255,0.95);
  1244. backdrop-filter: blur(20px);
  1245. border-top: 1px solid rgba(0,0,0,0.1);
  1246. display: flex;
  1247. justify-content: space-around;
  1248. padding: 12px 0;
  1249. z-index: 100;
  1250. }
  1251. .nav-item {
  1252. display: flex;
  1253. flex-direction: column;
  1254. align-items: center;
  1255. gap: 4px;
  1256. cursor: pointer;
  1257. transition: all 0.3s ease;
  1258. padding: 8px;
  1259. border-radius: 12px;
  1260. min-width: 60px;
  1261. }
  1262. .nav-item.active {
  1263. background: linear-gradient(135deg, #ff6b6b, #ffa726);
  1264. color: white;
  1265. }
  1266. .nav-item:not(.active):hover {
  1267. background: rgba(0,0,0,0.05);
  1268. }
  1269. .nav-icon {
  1270. font-size: 20px;
  1271. }
  1272. .nav-text {
  1273. font-size: 10px;
  1274. font-weight: 500;
  1275. }
  1276. /* 上传按钮特殊样式 */
  1277. .upload-btn {
  1278. position: relative;
  1279. background: linear-gradient(135deg, #ff6b6b, #ffa726) !important;
  1280. color: white !important;
  1281. border-radius: 50%;
  1282. width: 56px;
  1283. height: 56px;
  1284. margin-top: -20px;
  1285. box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4);
  1286. }
  1287. .upload-btn:hover {
  1288. transform: translateY(-2px);
  1289. box-shadow: 0 12px 35px rgba(255, 107, 107, 0.6);
  1290. }
  1291. .upload-icon {
  1292. font-size: 28px;
  1293. font-weight: bold;
  1294. }
  1295. /* 模态框样式 */
  1296. .modal {
  1297. position: fixed;
  1298. top: 0;
  1299. left: 0;
  1300. width: 100%;
  1301. height: 100%;
  1302. background: rgba(0,0,0,0.8);
  1303. backdrop-filter: blur(10px);
  1304. display: none;
  1305. align-items: center;
  1306. justify-content: center;
  1307. z-index: 1000;
  1308. animation: fadeIn 0.3s ease;
  1309. }
  1310. @keyframes fadeIn {
  1311. from { opacity: 0; }
  1312. to { opacity: 1; }
  1313. }
  1314. .modal-content {
  1315. background: white;
  1316. border-radius: 25px;
  1317. padding: 30px;
  1318. margin: 20px;
  1319. max-width: 350px;
  1320. width: 100%;
  1321. text-align: center;
  1322. transform: scale(0.9);
  1323. animation: modalPop 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
  1324. }
  1325. @keyframes modalPop {
  1326. to { transform: scale(1); }
  1327. }
  1328. .modal h3 {
  1329. font-size: 24px;
  1330. margin-bottom: 15px;
  1331. color: #333;
  1332. }
  1333. .modal p {
  1334. color: #666;
  1335. margin-bottom: 25px;
  1336. line-height: 1.5;
  1337. }
  1338. .modal-actions {
  1339. display: flex;
  1340. gap: 12px;
  1341. }
  1342. .btn {
  1343. flex: 1;
  1344. padding: 12px;
  1345. border: none;
  1346. border-radius: 12px;
  1347. font-size: 16px;
  1348. font-weight: 600;
  1349. cursor: pointer;
  1350. transition: all 0.3s ease;
  1351. }
  1352. .btn-primary {
  1353. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  1354. color: white;
  1355. }
  1356. .btn-primary:hover {
  1357. transform: translateY(-2px);
  1358. box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4);
  1359. }
  1360. .btn-secondary {
  1361. background: #f8f9fa;
  1362. color: #666;
  1363. }
  1364. .btn-secondary:hover {
  1365. background: #e9ecef;
  1366. }
  1367. /* 设置模态框样式 */
  1368. .settings-modal {
  1369. display: none;
  1370. position: fixed;
  1371. z-index: 2000;
  1372. left: 0;
  1373. top: 0;
  1374. width: 100%;
  1375. height: 100%;
  1376. background: rgba(0,0,0,0.6);
  1377. backdrop-filter: blur(5px);
  1378. animation: fadeIn 0.3s ease;
  1379. }
  1380. .settings-modal-content {
  1381. position: absolute;
  1382. left: 50%;
  1383. top: 50%;
  1384. transform: translate(-50%, -50%);
  1385. width: 90%;
  1386. max-width: 480px;
  1387. max-height: 85vh;
  1388. background: white;
  1389. border-radius: 20px;
  1390. box-shadow: 0 20px 60px rgba(0,0,0,0.3);
  1391. overflow: hidden;
  1392. animation: slideIn 0.3s ease;
  1393. }
  1394. @keyframes slideIn {
  1395. from { transform: translate(-50%, -50%) scale(0.9); opacity: 0; }
  1396. to { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  1397. }
  1398. .settings-header {
  1399. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  1400. color: white;
  1401. padding: 20px;
  1402. display: flex;
  1403. justify-content: space-between;
  1404. align-items: center;
  1405. }
  1406. .settings-header h2 {
  1407. font-size: 20px;
  1408. font-weight: 600;
  1409. margin: 0;
  1410. }
  1411. .close-btn {
  1412. background: none;
  1413. border: none;
  1414. color: white;
  1415. font-size: 24px;
  1416. cursor: pointer;
  1417. padding: 5px;
  1418. border-radius: 50%;
  1419. width: 35px;
  1420. height: 35px;
  1421. display: flex;
  1422. align-items: center;
  1423. justify-content: center;
  1424. transition: background 0.3s ease;
  1425. }
  1426. .close-btn:hover {
  1427. background: rgba(255,255,255,0.2);
  1428. }
  1429. .settings-body {
  1430. padding: 0;
  1431. max-height: 60vh;
  1432. overflow-y: auto;
  1433. }
  1434. .settings-section {
  1435. padding: 20px;
  1436. border-bottom: 1px solid #f0f0f0;
  1437. }
  1438. .settings-section:last-child {
  1439. border-bottom: none;
  1440. }
  1441. .settings-section h3 {
  1442. font-size: 16px;
  1443. font-weight: 600;
  1444. color: #333;
  1445. margin: 0 0 15px 0;
  1446. }
  1447. /* 个人资料样式 */
  1448. .profile-info {
  1449. display: flex;
  1450. flex-direction: column;
  1451. gap: 20px;
  1452. }
  1453. .profile-avatar {
  1454. display: flex;
  1455. justify-content: center;
  1456. }
  1457. .avatar-circle {
  1458. position: relative;
  1459. cursor: pointer;
  1460. }
  1461. .avatar-circle img {
  1462. width: 80px;
  1463. height: 80px;
  1464. border-radius: 50%;
  1465. border: 3px solid #ff6b6b;
  1466. }
  1467. .avatar-edit {
  1468. position: absolute;
  1469. bottom: 0;
  1470. right: 0;
  1471. background: #ff6b6b;
  1472. color: white;
  1473. width: 25px;
  1474. height: 25px;
  1475. border-radius: 50%;
  1476. display: flex;
  1477. align-items: center;
  1478. justify-content: center;
  1479. font-size: 12px;
  1480. border: 2px solid white;
  1481. }
  1482. .profile-details .form-group {
  1483. margin-bottom: 15px;
  1484. }
  1485. .profile-details label {
  1486. display: block;
  1487. font-size: 14px;
  1488. font-weight: 500;
  1489. color: #555;
  1490. margin-bottom: 5px;
  1491. }
  1492. .profile-details input,
  1493. .profile-details textarea {
  1494. width: 100%;
  1495. padding: 10px;
  1496. border: 1px solid #ddd;
  1497. border-radius: 8px;
  1498. font-size: 14px;
  1499. font-family: inherit;
  1500. transition: border-color 0.3s ease;
  1501. box-sizing: border-box;
  1502. }
  1503. .profile-details input:focus,
  1504. .profile-details textarea:focus {
  1505. outline: none;
  1506. border-color: #ff6b6b;
  1507. }
  1508. .profile-details textarea {
  1509. resize: vertical;
  1510. min-height: 60px;
  1511. }
  1512. /* 安全设置样式 */
  1513. .security-items {
  1514. display: flex;
  1515. flex-direction: column;
  1516. gap: 12px;
  1517. }
  1518. .security-item {
  1519. display: flex;
  1520. align-items: center;
  1521. justify-content: space-between;
  1522. padding: 12px;
  1523. background: #f8f9fa;
  1524. border-radius: 10px;
  1525. cursor: pointer;
  1526. transition: background 0.3s ease;
  1527. }
  1528. .security-item:hover {
  1529. background: #e9ecef;
  1530. }
  1531. .security-left {
  1532. display: flex;
  1533. align-items: center;
  1534. gap: 12px;
  1535. }
  1536. .security-icon {
  1537. font-size: 20px;
  1538. }
  1539. .security-title {
  1540. font-size: 14px;
  1541. font-weight: 500;
  1542. color: #333;
  1543. }
  1544. .security-desc {
  1545. font-size: 12px;
  1546. color: #666;
  1547. margin-top: 2px;
  1548. }
  1549. .arrow {
  1550. color: #999;
  1551. font-size: 16px;
  1552. }
  1553. /* 隐私设置样式 */
  1554. .privacy-items {
  1555. display: flex;
  1556. flex-direction: column;
  1557. gap: 15px;
  1558. }
  1559. .privacy-item {
  1560. display: flex;
  1561. align-items: center;
  1562. justify-content: space-between;
  1563. }
  1564. .privacy-left {
  1565. display: flex;
  1566. align-items: center;
  1567. gap: 12px;
  1568. flex: 1;
  1569. }
  1570. .privacy-icon {
  1571. font-size: 18px;
  1572. }
  1573. .privacy-title {
  1574. font-size: 14px;
  1575. font-weight: 500;
  1576. color: #333;
  1577. }
  1578. .privacy-desc {
  1579. font-size: 12px;
  1580. color: #666;
  1581. margin-top: 2px;
  1582. }
  1583. .privacy-select {
  1584. padding: 6px 10px;
  1585. border: 1px solid #ddd;
  1586. border-radius: 6px;
  1587. font-size: 12px;
  1588. background: white;
  1589. }
  1590. /* 开关样式 */
  1591. .switch {
  1592. position: relative;
  1593. display: inline-block;
  1594. width: 44px;
  1595. height: 24px;
  1596. }
  1597. .switch input {
  1598. opacity: 0;
  1599. width: 0;
  1600. height: 0;
  1601. }
  1602. .slider {
  1603. position: absolute;
  1604. cursor: pointer;
  1605. top: 0;
  1606. left: 0;
  1607. right: 0;
  1608. bottom: 0;
  1609. background-color: #ccc;
  1610. transition: 0.3s;
  1611. border-radius: 24px;
  1612. }
  1613. .slider:before {
  1614. position: absolute;
  1615. content: "";
  1616. height: 18px;
  1617. width: 18px;
  1618. left: 3px;
  1619. bottom: 3px;
  1620. background-color: white;
  1621. transition: 0.3s;
  1622. border-radius: 50%;
  1623. }
  1624. input:checked + .slider {
  1625. background-color: #ff6b6b;
  1626. }
  1627. input:checked + .slider:before {
  1628. transform: translateX(20px);
  1629. }
  1630. /* 应用设置样式 */
  1631. .app-items {
  1632. display: flex;
  1633. flex-direction: column;
  1634. gap: 12px;
  1635. }
  1636. .app-item {
  1637. display: flex;
  1638. align-items: center;
  1639. justify-content: space-between;
  1640. padding: 12px;
  1641. background: #f8f9fa;
  1642. border-radius: 10px;
  1643. cursor: pointer;
  1644. transition: background 0.3s ease;
  1645. }
  1646. .app-item:hover {
  1647. background: #e9ecef;
  1648. }
  1649. .app-left {
  1650. display: flex;
  1651. align-items: center;
  1652. gap: 12px;
  1653. }
  1654. .app-icon {
  1655. font-size: 18px;
  1656. }
  1657. .app-title {
  1658. font-size: 14px;
  1659. font-weight: 500;
  1660. color: #333;
  1661. }
  1662. .app-right {
  1663. display: flex;
  1664. align-items: center;
  1665. gap: 8px;
  1666. }
  1667. .version,
  1668. .cache-size {
  1669. font-size: 12px;
  1670. color: #666;
  1671. }
  1672. /* 设置底部 */
  1673. .settings-footer {
  1674. padding: 20px;
  1675. background: #f8f9fa;
  1676. display: flex;
  1677. gap: 12px;
  1678. }
  1679. .save-btn {
  1680. flex: 1;
  1681. padding: 12px;
  1682. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  1683. color: white;
  1684. border: none;
  1685. border-radius: 8px;
  1686. font-size: 14px;
  1687. font-weight: 500;
  1688. cursor: pointer;
  1689. transition: transform 0.2s ease;
  1690. }
  1691. .save-btn:hover {
  1692. transform: translateY(-1px);
  1693. }
  1694. .logout-btn {
  1695. flex: 1;
  1696. padding: 12px;
  1697. background: #dc3545;
  1698. color: white;
  1699. border: none;
  1700. border-radius: 8px;
  1701. font-size: 14px;
  1702. font-weight: 500;
  1703. cursor: pointer;
  1704. transition: background 0.3s ease;
  1705. }
  1706. .logout-btn:hover {
  1707. background: #c82333;
  1708. }
  1709. /* 新版设计中心样式 */
  1710. .design-preview-system {
  1711. margin: 20px;
  1712. margin-bottom: 25px;
  1713. }
  1714. .preview-container {
  1715. background: white;
  1716. border-radius: 20px;
  1717. padding: 20px;
  1718. box-shadow: 0 8px 30px rgba(0,0,0,0.1);
  1719. position: relative;
  1720. }
  1721. .preview-3d-enhanced {
  1722. position: relative;
  1723. height: 280px;
  1724. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  1725. border-radius: 15px;
  1726. overflow: hidden;
  1727. margin-bottom: 15px;
  1728. }
  1729. .model-3d-wrapper {
  1730. position: relative;
  1731. width: 100%;
  1732. height: 100%;
  1733. display: flex;
  1734. align-items: center;
  1735. justify-content: center;
  1736. }
  1737. #main3DModel {
  1738. font-size: 100px;
  1739. color: white;
  1740. z-index: 2;
  1741. position: relative;
  1742. animation: float 6s ease-in-out infinite;
  1743. transition: all 0.5s ease;
  1744. }
  1745. @keyframes float {
  1746. 0%, 100% { transform: translateY(0px) rotate(0deg); }
  1747. 50% { transform: translateY(-10px) rotate(5deg); }
  1748. }
  1749. .model-highlights {
  1750. position: absolute;
  1751. top: 0;
  1752. left: 0;
  1753. right: 0;
  1754. bottom: 0;
  1755. pointer-events: none;
  1756. z-index: 3;
  1757. }
  1758. .preview-controls {
  1759. position: absolute;
  1760. bottom: 15px;
  1761. right: 15px;
  1762. z-index: 4;
  1763. }
  1764. .control-group {
  1765. display: flex;
  1766. gap: 8px;
  1767. }
  1768. .control-btn {
  1769. width: 35px;
  1770. height: 35px;
  1771. border-radius: 50%;
  1772. background: rgba(255, 255, 255, 0.9);
  1773. border: none;
  1774. cursor: pointer;
  1775. font-size: 16px;
  1776. display: flex;
  1777. align-items: center;
  1778. justify-content: center;
  1779. transition: all 0.3s ease;
  1780. backdrop-filter: blur(10px);
  1781. }
  1782. .control-btn:hover {
  1783. background: white;
  1784. transform: scale(1.1);
  1785. }
  1786. /* 3D分区控制面板样式 */
  1787. .zone-control-panel {
  1788. margin: 20px;
  1789. background: white;
  1790. border-radius: 20px;
  1791. box-shadow: 0 8px 30px rgba(0,0,0,0.1);
  1792. overflow: hidden;
  1793. }
  1794. .panel-header {
  1795. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  1796. color: white;
  1797. padding: 15px 20px;
  1798. display: flex;
  1799. justify-content: space-between;
  1800. align-items: center;
  1801. }
  1802. .panel-header h3 {
  1803. margin: 0;
  1804. font-size: 16px;
  1805. font-weight: 600;
  1806. }
  1807. .expand-btn {
  1808. background: none;
  1809. border: none;
  1810. color: white;
  1811. font-size: 18px;
  1812. cursor: pointer;
  1813. transition: transform 0.3s ease;
  1814. }
  1815. .expand-btn:hover {
  1816. transform: scale(1.1);
  1817. }
  1818. .panel-content {
  1819. padding: 20px;
  1820. }
  1821. /* 部位选择器(胶囊式Tab)样式 */
  1822. .body-part-selector {
  1823. margin-bottom: 25px;
  1824. }
  1825. .part-tabs {
  1826. display: flex;
  1827. gap: 8px;
  1828. flex-wrap: wrap;
  1829. }
  1830. .part-tab {
  1831. background: #f8f9fa;
  1832. border: 2px solid transparent;
  1833. border-radius: 25px;
  1834. padding: 10px 15px;
  1835. cursor: pointer;
  1836. transition: all 0.3s ease;
  1837. display: flex;
  1838. align-items: center;
  1839. gap: 6px;
  1840. flex: 1;
  1841. min-width: 70px;
  1842. justify-content: center;
  1843. }
  1844. .part-tab:hover {
  1845. background: rgba(255, 107, 107, 0.1);
  1846. border-color: rgba(255, 107, 107, 0.3);
  1847. }
  1848. .part-tab.active {
  1849. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  1850. color: white;
  1851. border-color: #ff6b6b;
  1852. transform: translateY(-2px);
  1853. box-shadow: 0 5px 15px rgba(255, 107, 107, 0.4);
  1854. }
  1855. .tab-icon {
  1856. font-size: 14px;
  1857. }
  1858. .tab-text {
  1859. font-size: 12px;
  1860. font-weight: 500;
  1861. }
  1862. /* 色盘管理系统样式 */
  1863. .color-management-system {
  1864. margin: 20px;
  1865. background: white;
  1866. border-radius: 20px;
  1867. box-shadow: 0 8px 30px rgba(0,0,0,0.1);
  1868. overflow: hidden;
  1869. }
  1870. .color-system-header {
  1871. background: linear-gradient(45deg, #667eea, #764ba2);
  1872. color: white;
  1873. padding: 15px 20px;
  1874. display: flex;
  1875. justify-content: space-between;
  1876. align-items: center;
  1877. }
  1878. .color-system-header h3 {
  1879. margin: 0;
  1880. font-size: 16px;
  1881. font-weight: 600;
  1882. }
  1883. .color-actions {
  1884. display: flex;
  1885. gap: 8px;
  1886. }
  1887. .action-btn {
  1888. width: 32px;
  1889. height: 32px;
  1890. border-radius: 50%;
  1891. background: rgba(255, 255, 255, 0.2);
  1892. border: none;
  1893. color: white;
  1894. font-size: 14px;
  1895. cursor: pointer;
  1896. transition: all 0.3s ease;
  1897. display: flex;
  1898. align-items: center;
  1899. justify-content: center;
  1900. }
  1901. .action-btn:hover {
  1902. background: rgba(255, 255, 255, 0.3);
  1903. transform: scale(1.1);
  1904. }
  1905. .zone-color-memory {
  1906. padding: 15px 20px;
  1907. background: #f8f9fa;
  1908. border-bottom: 1px solid #e9ecef;
  1909. }
  1910. .current-part-info {
  1911. display: flex;
  1912. align-items: center;
  1913. gap: 10px;
  1914. }
  1915. .part-label {
  1916. font-size: 12px;
  1917. color: #666;
  1918. }
  1919. .part-name {
  1920. font-size: 14px;
  1921. font-weight: 600;
  1922. color: #333;
  1923. }
  1924. .color-indicator {
  1925. width: 20px;
  1926. height: 20px;
  1927. border-radius: 50%;
  1928. border: 2px solid white;
  1929. box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  1930. }
  1931. .master-color-picker {
  1932. padding: 20px;
  1933. }
  1934. .color-picker-section {
  1935. margin-bottom: 25px;
  1936. }
  1937. .color-picker-section:last-child {
  1938. margin-bottom: 0;
  1939. }
  1940. .color-picker-section h4 {
  1941. font-size: 14px;
  1942. font-weight: 600;
  1943. color: #333;
  1944. margin-bottom: 12px;
  1945. }
  1946. .enhanced-palette {
  1947. display: grid;
  1948. grid-template-columns: repeat(8, 1fr);
  1949. gap: 8px;
  1950. }
  1951. .color-swatch {
  1952. width: 35px;
  1953. height: 35px;
  1954. border-radius: 8px;
  1955. cursor: pointer;
  1956. transition: all 0.3s ease;
  1957. border: 2px solid transparent;
  1958. position: relative;
  1959. }
  1960. .color-swatch:hover {
  1961. transform: scale(1.1);
  1962. border-color: #333;
  1963. }
  1964. .color-swatch.active {
  1965. transform: scale(1.15);
  1966. border-color: #333;
  1967. box-shadow: 0 4px 12px rgba(0,0,0,0.3);
  1968. }
  1969. .custom-color-controls {
  1970. display: flex;
  1971. gap: 12px;
  1972. align-items: center;
  1973. }
  1974. #customColorPicker {
  1975. width: 40px;
  1976. height: 40px;
  1977. border: none;
  1978. border-radius: 8px;
  1979. cursor: pointer;
  1980. }
  1981. .add-custom-btn {
  1982. flex: 1;
  1983. padding: 8px 12px;
  1984. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  1985. color: white;
  1986. border: none;
  1987. border-radius: 6px;
  1988. font-size: 12px;
  1989. cursor: pointer;
  1990. transition: transform 0.2s ease;
  1991. }
  1992. .add-custom-btn:hover {
  1993. transform: translateY(-1px);
  1994. }
  1995. /* 历史配色库样式 */
  1996. .color-history-section {
  1997. padding: 20px;
  1998. border-top: 1px solid #e9ecef;
  1999. }
  2000. .color-history-section h4 {
  2001. font-size: 14px;
  2002. font-weight: 600;
  2003. color: #333;
  2004. margin-bottom: 15px;
  2005. }
  2006. .history-schemes {
  2007. display: flex;
  2008. flex-direction: column;
  2009. gap: 10px;
  2010. }
  2011. .scheme-item {
  2012. display: flex;
  2013. align-items: center;
  2014. gap: 12px;
  2015. padding: 10px;
  2016. background: #f8f9fa;
  2017. border-radius: 8px;
  2018. cursor: pointer;
  2019. transition: all 0.3s ease;
  2020. }
  2021. .scheme-item:hover {
  2022. background: rgba(255, 107, 107, 0.1);
  2023. }
  2024. .scheme-preview {
  2025. display: flex;
  2026. gap: 2px;
  2027. }
  2028. .scheme-color {
  2029. width: 20px;
  2030. height: 20px;
  2031. border-radius: 50%;
  2032. }
  2033. .scheme-name {
  2034. font-size: 12px;
  2035. color: #666;
  2036. }
  2037. /* 高级定制工具样式 */
  2038. .advanced-tools {
  2039. margin: 20px;
  2040. background: white;
  2041. border-radius: 20px;
  2042. box-shadow: 0 8px 30px rgba(0,0,0,0.1);
  2043. overflow: hidden;
  2044. }
  2045. .tools-header {
  2046. background: linear-gradient(45deg, #43e97b, #38f9d7);
  2047. color: white;
  2048. padding: 15px 20px;
  2049. }
  2050. .tools-header h3 {
  2051. margin: 0;
  2052. font-size: 16px;
  2053. font-weight: 600;
  2054. }
  2055. .advanced-tool-grid {
  2056. padding: 20px;
  2057. display: grid;
  2058. grid-template-columns: repeat(2, 1fr);
  2059. gap: 15px;
  2060. }
  2061. .advanced-tool-card {
  2062. background: #f8f9fa;
  2063. border-radius: 12px;
  2064. padding: 15px;
  2065. display: flex;
  2066. align-items: center;
  2067. gap: 12px;
  2068. cursor: pointer;
  2069. transition: all 0.3s ease;
  2070. border: 2px solid transparent;
  2071. }
  2072. .advanced-tool-card:hover {
  2073. background: white;
  2074. border-color: rgba(67, 233, 123, 0.3);
  2075. transform: translateY(-2px);
  2076. box-shadow: 0 8px 25px rgba(67, 233, 123, 0.2);
  2077. }
  2078. .advanced-tool-card .tool-icon {
  2079. font-size: 24px;
  2080. }
  2081. .tool-content {
  2082. flex: 1;
  2083. }
  2084. .advanced-tool-card .tool-title {
  2085. font-size: 14px;
  2086. font-weight: 600;
  2087. color: #333;
  2088. margin-bottom: 2px;
  2089. }
  2090. .tool-desc {
  2091. font-size: 11px;
  2092. color: #666;
  2093. }
  2094. /* 设计工具区域 */
  2095. .design-tools {
  2096. margin: 20px;
  2097. display: none;
  2098. }
  2099. .tool-grid {
  2100. display: grid;
  2101. grid-template-columns: repeat(2, 1fr);
  2102. gap: 15px;
  2103. margin-bottom: 20px;
  2104. }
  2105. .tool-card {
  2106. background: white;
  2107. border-radius: 15px;
  2108. padding: 20px;
  2109. text-align: center;
  2110. box-shadow: 0 5px 20px rgba(0,0,0,0.1);
  2111. cursor: pointer;
  2112. transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2113. }
  2114. .tool-card:hover {
  2115. transform: translateY(-5px);
  2116. box-shadow: 0 15px 40px rgba(0,0,0,0.2);
  2117. }
  2118. .tool-icon {
  2119. font-size: 40px;
  2120. margin-bottom: 10px;
  2121. display: block;
  2122. }
  2123. .tool-title {
  2124. font-size: 16px;
  2125. font-weight: 600;
  2126. color: #333;
  2127. }
  2128. /* 颜色选择器 */
  2129. .color-picker {
  2130. background: white;
  2131. border-radius: 15px;
  2132. padding: 20px;
  2133. margin-bottom: 20px;
  2134. box-shadow: 0 5px 20px rgba(0,0,0,0.1);
  2135. }
  2136. .color-palette {
  2137. display: grid;
  2138. grid-template-columns: repeat(7, 1fr);
  2139. gap: 8px;
  2140. margin-top: 15px;
  2141. }
  2142. @media (max-width: 380px) {
  2143. .color-palette {
  2144. grid-template-columns: repeat(5, 1fr);
  2145. gap: 6px;
  2146. }
  2147. }
  2148. .color-swatch {
  2149. width: 30px;
  2150. height: 30px;
  2151. border-radius: 50%;
  2152. cursor: pointer;
  2153. transition: all 0.3s ease;
  2154. border: 2px solid transparent;
  2155. }
  2156. .color-swatch:hover,
  2157. .color-swatch.active {
  2158. transform: scale(1.2);
  2159. border-color: #333;
  2160. box-shadow: 0 0 15px rgba(0,0,0,0.3);
  2161. }
  2162. .color-swatch[data-color="白色"]:hover,
  2163. .color-swatch[data-color="白色"].active {
  2164. border-color: #ff6b6b;
  2165. box-shadow: 0 0 15px rgba(255,107,107,0.5);
  2166. }
  2167. .color-swatch[title*="白色"] {
  2168. border: 2px solid #ddd !important;
  2169. }
  2170. .color-swatch[title*="白色"]:hover {
  2171. border-color: #ff6b6b !important;
  2172. }
  2173. /* 3D预览区 */
  2174. .preview-3d {
  2175. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  2176. border-radius: 15px;
  2177. height: 300px;
  2178. display: flex;
  2179. align-items: center;
  2180. justify-content: center;
  2181. color: white;
  2182. font-size: 18px;
  2183. margin-bottom: 20px;
  2184. box-shadow: 0 10px 30px rgba(0,0,0,0.2);
  2185. position: relative;
  2186. overflow: hidden;
  2187. }
  2188. .preview-3d::before {
  2189. content: '';
  2190. position: absolute;
  2191. top: 0;
  2192. left: 0;
  2193. right: 0;
  2194. bottom: 0;
  2195. background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="dots" width="20" height="20" patternUnits="userSpaceOnUse"><circle cx="10" cy="10" r="1" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23dots)"/></svg>');
  2196. }
  2197. .model-3d {
  2198. font-size: 80px;
  2199. z-index: 2;
  2200. position: relative;
  2201. animation: rotate3d 10s infinite linear;
  2202. }
  2203. @keyframes rotate3d {
  2204. 0% { transform: rotateY(0deg); }
  2205. 100% { transform: rotateY(360deg); }
  2206. }
  2207. /* 服装预览样式 */
  2208. .clothing-preview {
  2209. position: relative;
  2210. width: 280px;
  2211. height: 280px;
  2212. display: flex;
  2213. align-items: center;
  2214. justify-content: center;
  2215. z-index: 2;
  2216. }
  2217. .clothing-layer {
  2218. position: absolute;
  2219. top: 0;
  2220. left: 0;
  2221. width: 100%;
  2222. height: 100%;
  2223. display: flex;
  2224. align-items: center;
  2225. justify-content: center;
  2226. }
  2227. .part-image {
  2228. max-width: 100%;
  2229. max-height: 100%;
  2230. object-fit: contain;
  2231. transition: all 0.3s ease;
  2232. filter: drop-shadow(0 4px 8px rgba(0,0,0,0.3));
  2233. }
  2234. .part-image.highlighted {
  2235. filter: drop-shadow(0 0 20px #ffa726) drop-shadow(0 4px 8px rgba(0,0,0,0.3));
  2236. transform: scale(1.05);
  2237. }
  2238. .part-image.selected {
  2239. filter: drop-shadow(0 0 15px #ff6b6b) drop-shadow(0 4px 8px rgba(0,0,0,0.3));
  2240. }
  2241. /* 社区页面 */
  2242. .community-page {
  2243. display: none;
  2244. }
  2245. .community-header {
  2246. background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
  2247. padding: 20px;
  2248. color: white;
  2249. text-align: center;
  2250. }
  2251. .community-header-top {
  2252. display: flex;
  2253. justify-content: space-between;
  2254. align-items: center;
  2255. margin-bottom: 10px;
  2256. }
  2257. /* 发布按钮样式 */
  2258. .publish-btn {
  2259. background: rgba(255, 255, 255, 0.2);
  2260. border: 1px solid rgba(255, 255, 255, 0.3);
  2261. color: white;
  2262. padding: 8px 16px;
  2263. border-radius: 20px;
  2264. font-size: 14px;
  2265. cursor: pointer;
  2266. transition: all 0.3s ease;
  2267. display: flex;
  2268. align-items: center;
  2269. gap: 6px;
  2270. }
  2271. .publish-btn:hover {
  2272. background: rgba(255, 255, 255, 0.3);
  2273. transform: translateY(-2px);
  2274. }
  2275. .publish-icon {
  2276. font-size: 16px;
  2277. }
  2278. /* 上传模态框样式 */
  2279. .upload-modal {
  2280. position: fixed;
  2281. top: 0;
  2282. left: 0;
  2283. width: 100%;
  2284. height: 100%;
  2285. background: rgba(0, 0, 0, 0.8);
  2286. backdrop-filter: blur(10px);
  2287. display: none;
  2288. align-items: center;
  2289. justify-content: center;
  2290. z-index: 1000;
  2291. animation: fadeIn 0.3s ease;
  2292. }
  2293. .upload-modal-content {
  2294. background: white;
  2295. border-radius: 25px;
  2296. padding: 0;
  2297. margin: 20px;
  2298. max-width: 380px;
  2299. width: 100%;
  2300. max-height: 90vh;
  2301. overflow-y: auto;
  2302. transform: scale(0.9);
  2303. animation: modalPop 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
  2304. }
  2305. /* 步骤指示器 */
  2306. .upload-steps {
  2307. display: flex;
  2308. justify-content: space-between;
  2309. padding: 20px 30px 0;
  2310. margin-bottom: 20px;
  2311. }
  2312. .step {
  2313. display: flex;
  2314. flex-direction: column;
  2315. align-items: center;
  2316. flex: 1;
  2317. position: relative;
  2318. }
  2319. .step:not(:last-child)::after {
  2320. content: '';
  2321. position: absolute;
  2322. top: 15px;
  2323. left: 60%;
  2324. width: 40px;
  2325. height: 2px;
  2326. background: #e9ecef;
  2327. z-index: 1;
  2328. }
  2329. .step.active:not(:last-child)::after {
  2330. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  2331. }
  2332. .step-number {
  2333. width: 30px;
  2334. height: 30px;
  2335. border-radius: 50%;
  2336. background: #e9ecef;
  2337. color: #666;
  2338. display: flex;
  2339. align-items: center;
  2340. justify-content: center;
  2341. font-size: 14px;
  2342. font-weight: 600;
  2343. margin-bottom: 8px;
  2344. position: relative;
  2345. z-index: 2;
  2346. transition: all 0.3s ease;
  2347. }
  2348. .step.active .step-number {
  2349. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  2350. color: white;
  2351. }
  2352. .step-label {
  2353. font-size: 12px;
  2354. color: #666;
  2355. text-align: center;
  2356. }
  2357. .step.active .step-label {
  2358. color: #333;
  2359. font-weight: 600;
  2360. }
  2361. /* 上传步骤内容 */
  2362. .upload-step {
  2363. display: none;
  2364. padding: 0 30px 20px;
  2365. }
  2366. .upload-step.active {
  2367. display: block;
  2368. }
  2369. .upload-step h3 {
  2370. font-size: 20px;
  2371. margin-bottom: 20px;
  2372. color: #333;
  2373. text-align: center;
  2374. }
  2375. /* 作品类型选择 */
  2376. .work-types {
  2377. display: flex;
  2378. flex-direction: column;
  2379. gap: 12px;
  2380. }
  2381. .work-type {
  2382. border: 2px solid #e9ecef;
  2383. border-radius: 15px;
  2384. padding: 20px;
  2385. cursor: pointer;
  2386. transition: all 0.3s ease;
  2387. text-align: center;
  2388. }
  2389. .work-type:hover {
  2390. border-color: #ff6b6b;
  2391. background: rgba(255, 107, 107, 0.05);
  2392. }
  2393. .work-type.selected {
  2394. border-color: #ff6b6b;
  2395. background: linear-gradient(135deg, rgba(255, 107, 107, 0.1), rgba(255, 167, 38, 0.1));
  2396. }
  2397. .type-icon {
  2398. font-size: 32px;
  2399. margin-bottom: 10px;
  2400. }
  2401. .type-name {
  2402. font-size: 16px;
  2403. font-weight: 600;
  2404. color: #333;
  2405. margin-bottom: 5px;
  2406. }
  2407. .type-desc {
  2408. font-size: 12px;
  2409. color: #666;
  2410. }
  2411. /* 上传选项 */
  2412. .upload-options {
  2413. display: flex;
  2414. flex-direction: column;
  2415. gap: 20px;
  2416. }
  2417. .upload-section {
  2418. border: 1px solid #e9ecef;
  2419. border-radius: 15px;
  2420. padding: 20px;
  2421. }
  2422. .upload-section h4 {
  2423. font-size: 14px;
  2424. font-weight: 600;
  2425. color: #333;
  2426. margin-bottom: 15px;
  2427. }
  2428. /* 文件上传区域 */
  2429. .file-upload-area {
  2430. border: 2px dashed #ddd;
  2431. border-radius: 12px;
  2432. padding: 30px 20px;
  2433. text-align: center;
  2434. cursor: pointer;
  2435. transition: all 0.3s ease;
  2436. background: #fafafa;
  2437. }
  2438. .file-upload-area:hover {
  2439. border-color: #ff6b6b;
  2440. background: rgba(255, 107, 107, 0.05);
  2441. }
  2442. .upload-placeholder {
  2443. display: flex;
  2444. flex-direction: column;
  2445. align-items: center;
  2446. gap: 8px;
  2447. }
  2448. .upload-icon {
  2449. font-size: 32px;
  2450. color: #666;
  2451. }
  2452. .upload-text {
  2453. font-size: 14px;
  2454. font-weight: 600;
  2455. color: #333;
  2456. }
  2457. .upload-hint {
  2458. font-size: 12px;
  2459. color: #666;
  2460. }
  2461. /* 上传预览 */
  2462. .upload-preview {
  2463. display: grid;
  2464. grid-template-columns: repeat(3, 1fr);
  2465. gap: 10px;
  2466. margin-top: 15px;
  2467. }
  2468. .preview-item {
  2469. position: relative;
  2470. aspect-ratio: 1;
  2471. border-radius: 8px;
  2472. overflow: hidden;
  2473. background: #f8f9fa;
  2474. }
  2475. .preview-item img {
  2476. width: 100%;
  2477. height: 100%;
  2478. object-fit: cover;
  2479. }
  2480. .preview-remove {
  2481. position: absolute;
  2482. top: 5px;
  2483. right: 5px;
  2484. width: 20px;
  2485. height: 20px;
  2486. border-radius: 50%;
  2487. background: rgba(0, 0, 0, 0.7);
  2488. color: white;
  2489. border: none;
  2490. cursor: pointer;
  2491. font-size: 12px;
  2492. display: flex;
  2493. align-items: center;
  2494. justify-content: center;
  2495. }
  2496. /* 我的设计网格 */
  2497. .my-designs-grid {
  2498. display: grid;
  2499. grid-template-columns: repeat(3, 1fr);
  2500. gap: 10px;
  2501. }
  2502. .design-item {
  2503. text-align: center;
  2504. cursor: pointer;
  2505. padding: 10px;
  2506. border-radius: 8px;
  2507. transition: all 0.3s ease;
  2508. }
  2509. .design-item:hover {
  2510. background: rgba(255, 107, 107, 0.05);
  2511. }
  2512. .design-item.selected {
  2513. background: rgba(255, 107, 107, 0.1);
  2514. border: 2px solid #ff6b6b;
  2515. }
  2516. .design-preview {
  2517. width: 60px;
  2518. height: 60px;
  2519. border-radius: 8px;
  2520. background: linear-gradient(45deg, #a8edea 0%, #fed6e3 100%);
  2521. display: flex;
  2522. align-items: center;
  2523. justify-content: center;
  2524. font-size: 24px;
  2525. margin: 0 auto 8px;
  2526. }
  2527. .design-name {
  2528. font-size: 12px;
  2529. color: #666;
  2530. }
  2531. /* 描述表单 */
  2532. .description-form {
  2533. display: flex;
  2534. flex-direction: column;
  2535. gap: 20px;
  2536. }
  2537. .form-group {
  2538. position: relative;
  2539. }
  2540. .form-group label {
  2541. display: block;
  2542. font-size: 14px;
  2543. font-weight: 600;
  2544. color: #333;
  2545. margin-bottom: 8px;
  2546. }
  2547. .form-group input,
  2548. .form-group textarea,
  2549. .form-group select {
  2550. width: 100%;
  2551. padding: 12px;
  2552. border: 2px solid #e9ecef;
  2553. border-radius: 8px;
  2554. font-size: 14px;
  2555. transition: all 0.3s ease;
  2556. resize: none;
  2557. }
  2558. .form-group input:focus,
  2559. .form-group textarea:focus,
  2560. .form-group select:focus {
  2561. outline: none;
  2562. border-color: #ff6b6b;
  2563. box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.1);
  2564. }
  2565. .form-group textarea {
  2566. height: 80px;
  2567. }
  2568. .char-count {
  2569. position: absolute;
  2570. bottom: -20px;
  2571. right: 0;
  2572. font-size: 12px;
  2573. color: #666;
  2574. }
  2575. /* 标签容器 */
  2576. .tags-container {
  2577. display: flex;
  2578. flex-direction: column;
  2579. gap: 12px;
  2580. }
  2581. .popular-tags {
  2582. display: flex;
  2583. flex-wrap: wrap;
  2584. gap: 8px;
  2585. }
  2586. .tag {
  2587. background: #f8f9fa;
  2588. color: #666;
  2589. padding: 6px 12px;
  2590. border-radius: 20px;
  2591. font-size: 12px;
  2592. cursor: pointer;
  2593. transition: all 0.3s ease;
  2594. border: 1px solid transparent;
  2595. }
  2596. .tag:hover {
  2597. background: rgba(255, 107, 107, 0.1);
  2598. color: #ff6b6b;
  2599. }
  2600. .tag.selected {
  2601. background: #ff6b6b;
  2602. color: white;
  2603. }
  2604. /* 发布设置 */
  2605. .publish-settings {
  2606. display: flex;
  2607. flex-direction: column;
  2608. gap: 25px;
  2609. }
  2610. .setting-group {
  2611. border: 1px solid #e9ecef;
  2612. border-radius: 12px;
  2613. padding: 20px;
  2614. }
  2615. .setting-group > label {
  2616. display: block;
  2617. font-size: 16px;
  2618. font-weight: 600;
  2619. color: #333;
  2620. margin-bottom: 15px;
  2621. }
  2622. .radio-group {
  2623. display: flex;
  2624. flex-direction: column;
  2625. gap: 12px;
  2626. }
  2627. .radio-option,
  2628. .checkbox-option {
  2629. display: flex;
  2630. align-items: flex-start;
  2631. gap: 12px;
  2632. cursor: pointer;
  2633. padding: 12px;
  2634. border-radius: 8px;
  2635. transition: all 0.3s ease;
  2636. }
  2637. .radio-option:hover,
  2638. .checkbox-option:hover {
  2639. background: rgba(255, 107, 107, 0.05);
  2640. }
  2641. .radio-option input,
  2642. .checkbox-option input {
  2643. display: none;
  2644. }
  2645. .radio-custom,
  2646. .checkbox-custom {
  2647. width: 20px;
  2648. height: 20px;
  2649. border: 2px solid #ddd;
  2650. border-radius: 50%;
  2651. position: relative;
  2652. transition: all 0.3s ease;
  2653. flex-shrink: 0;
  2654. margin-top: 2px;
  2655. }
  2656. .checkbox-custom {
  2657. border-radius: 4px;
  2658. }
  2659. .radio-option input:checked + .radio-custom,
  2660. .checkbox-option input:checked + .checkbox-custom {
  2661. border-color: #ff6b6b;
  2662. background: #ff6b6b;
  2663. }
  2664. .radio-option input:checked + .radio-custom::after {
  2665. content: '';
  2666. position: absolute;
  2667. top: 50%;
  2668. left: 50%;
  2669. transform: translate(-50%, -50%);
  2670. width: 8px;
  2671. height: 8px;
  2672. border-radius: 50%;
  2673. background: white;
  2674. }
  2675. .checkbox-option input:checked + .checkbox-custom::after {
  2676. content: '✓';
  2677. position: absolute;
  2678. top: 50%;
  2679. left: 50%;
  2680. transform: translate(-50%, -50%);
  2681. color: white;
  2682. font-size: 12px;
  2683. font-weight: bold;
  2684. }
  2685. .option-content {
  2686. flex: 1;
  2687. }
  2688. .option-title {
  2689. font-size: 14px;
  2690. font-weight: 600;
  2691. color: #333;
  2692. margin-bottom: 4px;
  2693. }
  2694. .option-desc {
  2695. font-size: 12px;
  2696. color: #666;
  2697. line-height: 1.4;
  2698. }
  2699. /* 模态框底部 */
  2700. .upload-modal-footer {
  2701. padding: 20px 30px;
  2702. border-top: 1px solid #e9ecef;
  2703. display: flex;
  2704. gap: 12px;
  2705. justify-content: flex-end;
  2706. }
  2707. .btn-outline {
  2708. background: transparent;
  2709. border: 2px solid #ff6b6b;
  2710. color: #ff6b6b;
  2711. }
  2712. .btn-outline:hover {
  2713. background: #ff6b6b;
  2714. color: white;
  2715. }
  2716. /* 草稿箱和我的作品样式 */
  2717. .drafts-content,
  2718. .my-works-content {
  2719. max-width: 400px;
  2720. max-height: 80vh;
  2721. overflow-y: auto;
  2722. }
  2723. .drafts-list,
  2724. .works-content {
  2725. max-height: 400px;
  2726. overflow-y: auto;
  2727. margin-bottom: 20px;
  2728. }
  2729. .draft-item,
  2730. .work-item {
  2731. display: flex;
  2732. align-items: center;
  2733. gap: 15px;
  2734. padding: 15px;
  2735. border: 1px solid #e9ecef;
  2736. border-radius: 12px;
  2737. margin-bottom: 12px;
  2738. transition: all 0.3s ease;
  2739. }
  2740. .draft-item:hover,
  2741. .work-item:hover {
  2742. border-color: #ff6b6b;
  2743. background: rgba(255, 107, 107, 0.05);
  2744. }
  2745. .draft-preview,
  2746. .work-preview {
  2747. width: 50px;
  2748. height: 50px;
  2749. border-radius: 8px;
  2750. background: linear-gradient(45deg, #a8edea 0%, #fed6e3 100%);
  2751. display: flex;
  2752. align-items: center;
  2753. justify-content: center;
  2754. font-size: 20px;
  2755. flex-shrink: 0;
  2756. }
  2757. .draft-info,
  2758. .work-info {
  2759. flex: 1;
  2760. }
  2761. .draft-title,
  2762. .work-title {
  2763. font-size: 14px;
  2764. font-weight: 600;
  2765. color: #333;
  2766. margin-bottom: 4px;
  2767. }
  2768. .draft-time {
  2769. font-size: 12px;
  2770. color: #666;
  2771. }
  2772. .work-stats {
  2773. display: flex;
  2774. gap: 12px;
  2775. font-size: 12px;
  2776. color: #666;
  2777. }
  2778. .draft-actions,
  2779. .work-actions {
  2780. display: flex;
  2781. gap: 8px;
  2782. }
  2783. .draft-actions button,
  2784. .work-actions button {
  2785. padding: 6px 12px;
  2786. border: 1px solid #ddd;
  2787. border-radius: 6px;
  2788. background: white;
  2789. color: #666;
  2790. font-size: 12px;
  2791. cursor: pointer;
  2792. transition: all 0.3s ease;
  2793. }
  2794. .draft-actions button:hover,
  2795. .work-actions button:hover {
  2796. border-color: #ff6b6b;
  2797. color: #ff6b6b;
  2798. }
  2799. /* 作品标签页 */
  2800. .works-tabs {
  2801. display: flex;
  2802. border-bottom: 1px solid #e9ecef;
  2803. margin-bottom: 20px;
  2804. }
  2805. .tab {
  2806. flex: 1;
  2807. padding: 12px;
  2808. text-align: center;
  2809. cursor: pointer;
  2810. border-bottom: 2px solid transparent;
  2811. transition: all 0.3s ease;
  2812. font-size: 14px;
  2813. font-weight: 500;
  2814. }
  2815. .tab.active {
  2816. color: #ff6b6b;
  2817. border-bottom-color: #ff6b6b;
  2818. }
  2819. .tab:hover {
  2820. background: rgba(255, 107, 107, 0.05);
  2821. }
  2822. /* 数据分析 */
  2823. .analytics-summary {
  2824. display: grid;
  2825. grid-template-columns: repeat(3, 1fr);
  2826. gap: 15px;
  2827. text-align: center;
  2828. }
  2829. .analytics-item {
  2830. padding: 20px;
  2831. border: 1px solid #e9ecef;
  2832. border-radius: 12px;
  2833. background: linear-gradient(135deg, rgba(255, 107, 107, 0.05), rgba(255, 167, 38, 0.05));
  2834. }
  2835. .analytics-number {
  2836. font-size: 24px;
  2837. font-weight: 700;
  2838. color: #ff6b6b;
  2839. margin-bottom: 5px;
  2840. }
  2841. .analytics-label {
  2842. font-size: 12px;
  2843. color: #666;
  2844. }
  2845. /* 响应式调整 */
  2846. @media (max-width: 380px) {
  2847. .upload-modal-content {
  2848. margin: 10px;
  2849. max-width: calc(100% - 20px);
  2850. }
  2851. .upload-steps {
  2852. padding: 15px 20px 0;
  2853. }
  2854. .upload-step {
  2855. padding: 0 20px 15px;
  2856. }
  2857. .upload-modal-footer {
  2858. padding: 15px 20px;
  2859. }
  2860. /* AI推荐引擎小屏幕优化 */
  2861. .ai-engine-card {
  2862. margin: 15px;
  2863. padding: 20px;
  2864. }
  2865. .ai-quick-actions {
  2866. gap: 10px;
  2867. }
  2868. .quick-action {
  2869. padding: 12px 10px;
  2870. min-height: 45px;
  2871. }
  2872. .action-text {
  2873. font-size: 13px;
  2874. }
  2875. .preview-items {
  2876. gap: 10px;
  2877. }
  2878. .preview-item {
  2879. padding: 12px 10px;
  2880. min-height: 65px;
  2881. gap: 10px;
  2882. }
  2883. .preview-image {
  2884. width: 40px;
  2885. height: 40px;
  2886. font-size: 20px;
  2887. }
  2888. .preview-title {
  2889. font-size: 13px;
  2890. }
  2891. .preview-tags {
  2892. font-size: 10px;
  2893. }
  2894. .ai-preview-results h4 {
  2895. font-size: 15px;
  2896. margin-bottom: 12px;
  2897. }
  2898. }
  2899. @media (max-width: 320px) {
  2900. /* 极小屏幕优化 */
  2901. .ai-quick-actions {
  2902. grid-template-columns: 1fr;
  2903. gap: 8px;
  2904. }
  2905. .quick-action {
  2906. justify-content: center;
  2907. text-align: center;
  2908. }
  2909. .preview-items {
  2910. grid-template-columns: 1fr;
  2911. gap: 8px;
  2912. }
  2913. }
  2914. .community-stats {
  2915. display: flex;
  2916. justify-content: space-around;
  2917. margin: 20px 0;
  2918. }
  2919. .stat-item {
  2920. text-align: center;
  2921. }
  2922. .stat-number {
  2923. font-size: 24px;
  2924. font-weight: 700;
  2925. }
  2926. .stat-label {
  2927. font-size: 12px;
  2928. opacity: 0.8;
  2929. }
  2930. /* 个人中心 */
  2931. .profile-page {
  2932. display: none;
  2933. }
  2934. .profile-header {
  2935. background: linear-gradient(45deg, #ff9a9e 0%, #fecfef 100%);
  2936. padding: 30px 20px;
  2937. text-align: center;
  2938. color: white;
  2939. }
  2940. .avatar {
  2941. width: 80px;
  2942. height: 80px;
  2943. border-radius: 50%;
  2944. background: rgba(255,255,255,0.3);
  2945. display: flex;
  2946. align-items: center;
  2947. justify-content: center;
  2948. font-size: 36px;
  2949. margin: 0 auto 15px;
  2950. border: 3px solid rgba(255,255,255,0.5);
  2951. }
  2952. .profile-menu {
  2953. padding: 20px;
  2954. }
  2955. .menu-item {
  2956. display: flex;
  2957. align-items: center;
  2958. justify-content: space-between;
  2959. padding: 15px;
  2960. background: white;
  2961. border-radius: 12px;
  2962. margin-bottom: 10px;
  2963. box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  2964. cursor: pointer;
  2965. transition: all 0.3s ease;
  2966. }
  2967. .menu-item:hover {
  2968. transform: translateX(5px);
  2969. box-shadow: 0 5px 20px rgba(0,0,0,0.15);
  2970. }
  2971. .menu-left {
  2972. display: flex;
  2973. align-items: center;
  2974. gap: 12px;
  2975. }
  2976. .menu-icon {
  2977. font-size: 18px;
  2978. color: #667eea;
  2979. }
  2980. /* 响应式设计 */
  2981. @media (max-width: 480px) {
  2982. .app-container {
  2983. max-width: 100%;
  2984. }
  2985. .bottom-nav {
  2986. width: 100%;
  2987. }
  2988. }
  2989. /* 滚动条样式 */
  2990. ::-webkit-scrollbar {
  2991. width: 4px;
  2992. }
  2993. ::-webkit-scrollbar-track {
  2994. background: transparent;
  2995. }
  2996. ::-webkit-scrollbar-thumb {
  2997. background: rgba(0,0,0,0.2);
  2998. border-radius: 2px;
  2999. }
  3000. /* 页面切换动画 */
  3001. .page {
  3002. transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  3003. }
  3004. .page.fade-out {
  3005. opacity: 0;
  3006. transform: translateX(-20px);
  3007. }
  3008. .page.fade-in {
  3009. opacity: 1;
  3010. transform: translateX(0);
  3011. }
  3012. /* 3D试衣间样式 */
  3013. .fitting-flow-nav {
  3014. display: flex;
  3015. justify-content: center;
  3016. margin: 20px 0;
  3017. padding: 0 20px;
  3018. }
  3019. .flow-step {
  3020. display: flex;
  3021. flex-direction: column;
  3022. align-items: center;
  3023. padding: 15px 20px;
  3024. margin: 0 10px;
  3025. border-radius: 12px;
  3026. background: #f8f9fa;
  3027. border: 2px solid transparent;
  3028. cursor: pointer;
  3029. transition: all 0.3s ease;
  3030. min-width: 80px;
  3031. }
  3032. .flow-step.active {
  3033. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  3034. color: white;
  3035. border-color: #667eea;
  3036. }
  3037. .step-icon {
  3038. font-size: 20px;
  3039. margin-bottom: 5px;
  3040. }
  3041. .step-text {
  3042. font-size: 12px;
  3043. font-weight: 600;
  3044. text-align: center;
  3045. }
  3046. .fitting-step {
  3047. margin: 0 20px;
  3048. }
  3049. .step-container {
  3050. background: white;
  3051. border-radius: 15px;
  3052. padding: 25px;
  3053. box-shadow: 0 5px 20px rgba(0,0,0,0.1);
  3054. }
  3055. .step-title {
  3056. font-size: 18px;
  3057. font-weight: 700;
  3058. margin-bottom: 20px;
  3059. color: #333;
  3060. text-align: center;
  3061. }
  3062. /* 照片上传样式 */
  3063. .upload-methods {
  3064. display: grid;
  3065. grid-template-columns: repeat(2, 1fr);
  3066. gap: 15px;
  3067. margin-bottom: 25px;
  3068. }
  3069. .upload-method {
  3070. padding: 20px;
  3071. border: 2px solid #e9ecef;
  3072. border-radius: 12px;
  3073. text-align: center;
  3074. cursor: pointer;
  3075. transition: all 0.3s ease;
  3076. }
  3077. .upload-method.active {
  3078. border-color: #667eea;
  3079. background: #f8f9ff;
  3080. }
  3081. .method-icon {
  3082. font-size: 24px;
  3083. margin-bottom: 10px;
  3084. }
  3085. .method-title {
  3086. font-weight: 600;
  3087. font-size: 14px;
  3088. margin-bottom: 5px;
  3089. }
  3090. .method-desc {
  3091. font-size: 12px;
  3092. color: #666;
  3093. }
  3094. .camera-interface, .gallery-interface {
  3095. margin: 20px 0;
  3096. }
  3097. .camera-preview {
  3098. height: 300px;
  3099. background: #f8f9fa;
  3100. border-radius: 12px;
  3101. position: relative;
  3102. display: flex;
  3103. align-items: center;
  3104. justify-content: center;
  3105. margin-bottom: 15px;
  3106. border: 2px dashed #dee2e6;
  3107. }
  3108. .camera-placeholder {
  3109. text-align: center;
  3110. color: #666;
  3111. }
  3112. .camera-icon {
  3113. font-size: 48px;
  3114. margin-bottom: 15px;
  3115. }
  3116. .camera-text {
  3117. font-size: 16px;
  3118. font-weight: 600;
  3119. margin-bottom: 5px;
  3120. }
  3121. .camera-hint {
  3122. font-size: 12px;
  3123. opacity: 0.7;
  3124. }
  3125. .pose-guide {
  3126. position: absolute;
  3127. top: 20px;
  3128. right: 20px;
  3129. background: rgba(0,0,0,0.7);
  3130. color: white;
  3131. padding: 10px;
  3132. border-radius: 8px;
  3133. text-align: center;
  3134. font-size: 12px;
  3135. }
  3136. .guide-silhouette {
  3137. font-size: 24px;
  3138. margin-bottom: 5px;
  3139. }
  3140. .camera-controls {
  3141. display: flex;
  3142. justify-content: center;
  3143. gap: 10px;
  3144. }
  3145. .camera-btn {
  3146. padding: 10px 20px;
  3147. border: none;
  3148. border-radius: 8px;
  3149. background: #667eea;
  3150. color: white;
  3151. font-size: 14px;
  3152. cursor: pointer;
  3153. transition: all 0.3s ease;
  3154. }
  3155. .camera-btn:hover {
  3156. background: #5a6fd8;
  3157. transform: translateY(-2px);
  3158. }
  3159. .camera-btn.capture {
  3160. background: #ff6b6b;
  3161. }
  3162. .camera-btn.switch {
  3163. background: #4ecdc4;
  3164. }
  3165. .upload-zone {
  3166. height: 200px;
  3167. border: 2px dashed #dee2e6;
  3168. border-radius: 12px;
  3169. display: flex;
  3170. flex-direction: column;
  3171. align-items: center;
  3172. justify-content: center;
  3173. cursor: pointer;
  3174. transition: all 0.3s ease;
  3175. }
  3176. .upload-zone:hover {
  3177. border-color: #667eea;
  3178. background: #f8f9ff;
  3179. }
  3180. .upload-icon {
  3181. font-size: 36px;
  3182. margin-bottom: 10px;
  3183. }
  3184. .upload-text {
  3185. font-weight: 600;
  3186. margin-bottom: 5px;
  3187. }
  3188. .upload-hint {
  3189. font-size: 12px;
  3190. color: #666;
  3191. }
  3192. .crop-area {
  3193. margin-top: 20px;
  3194. }
  3195. .crop-container {
  3196. position: relative;
  3197. height: 300px;
  3198. background: #f8f9fa;
  3199. border-radius: 12px;
  3200. overflow: hidden;
  3201. }
  3202. .crop-controls {
  3203. display: flex;
  3204. justify-content: center;
  3205. gap: 10px;
  3206. margin-top: 15px;
  3207. }
  3208. .crop-btn {
  3209. padding: 8px 16px;
  3210. border: 1px solid #dee2e6;
  3211. border-radius: 6px;
  3212. background: white;
  3213. cursor: pointer;
  3214. transition: all 0.3s ease;
  3215. }
  3216. .crop-btn.confirm {
  3217. background: #28a745;
  3218. color: white;
  3219. border-color: #28a745;
  3220. }
  3221. /* 姿势校准样式 */
  3222. .pose-calibration {
  3223. margin-top: 25px;
  3224. padding: 20px;
  3225. background: #f8f9fa;
  3226. border-radius: 12px;
  3227. }
  3228. .calibration-display {
  3229. display: grid;
  3230. grid-template-columns: 1fr 1fr;
  3231. gap: 20px;
  3232. margin: 20px 0;
  3233. }
  3234. .body-keypoints {
  3235. display: flex;
  3236. flex-direction: column;
  3237. gap: 10px;
  3238. }
  3239. .keypoint {
  3240. padding: 10px;
  3241. background: white;
  3242. border-radius: 8px;
  3243. border-left: 4px solid #28a745;
  3244. font-size: 14px;
  3245. }
  3246. .calibration-status {
  3247. display: flex;
  3248. flex-direction: column;
  3249. gap: 10px;
  3250. }
  3251. .status-item {
  3252. display: flex;
  3253. align-items: center;
  3254. gap: 10px;
  3255. font-size: 14px;
  3256. }
  3257. .status-icon {
  3258. font-size: 16px;
  3259. }
  3260. .calibration-actions {
  3261. display: flex;
  3262. justify-content: center;
  3263. gap: 15px;
  3264. margin-top: 20px;
  3265. }
  3266. .calib-btn {
  3267. padding: 10px 20px;
  3268. border: 1px solid #dee2e6;
  3269. border-radius: 8px;
  3270. background: white;
  3271. cursor: pointer;
  3272. transition: all 0.3s ease;
  3273. }
  3274. .calib-btn.next {
  3275. background: #28a745;
  3276. color: white;
  3277. border-color: #28a745;
  3278. }
  3279. /* 服装选择器样式 */
  3280. .clothing-tabs {
  3281. display: flex;
  3282. margin-bottom: 25px;
  3283. border-bottom: 1px solid #e9ecef;
  3284. }
  3285. .clothing-tab {
  3286. flex: 1;
  3287. display: flex;
  3288. align-items: center;
  3289. justify-content: center;
  3290. gap: 8px;
  3291. padding: 15px 10px;
  3292. cursor: pointer;
  3293. border-bottom: 2px solid transparent;
  3294. transition: all 0.3s ease;
  3295. }
  3296. .clothing-tab.active {
  3297. border-bottom-color: #667eea;
  3298. color: #667eea;
  3299. }
  3300. .tab-icon {
  3301. font-size: 16px;
  3302. }
  3303. .tab-text {
  3304. font-weight: 600;
  3305. font-size: 14px;
  3306. }
  3307. .tab-count {
  3308. background: #e9ecef;
  3309. color: #666;
  3310. padding: 2px 6px;
  3311. border-radius: 10px;
  3312. font-size: 11px;
  3313. }
  3314. .clothing-tab.active .tab-count {
  3315. background: #667eea;
  3316. color: white;
  3317. }
  3318. .design-grid, .trending-grid, .brand-grid {
  3319. display: grid;
  3320. grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  3321. gap: 15px;
  3322. }
  3323. .design-item, .trending-item, .brand-item {
  3324. background: white;
  3325. border-radius: 12px;
  3326. overflow: hidden;
  3327. box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  3328. cursor: pointer;
  3329. transition: all 0.3s ease;
  3330. }
  3331. .design-item:hover, .trending-item:hover, .brand-item:hover {
  3332. transform: translateY(-5px);
  3333. box-shadow: 0 5px 20px rgba(0,0,0,0.15);
  3334. }
  3335. .design-preview, .trending-preview, .brand-preview {
  3336. position: relative;
  3337. height: 120px;
  3338. overflow: hidden;
  3339. }
  3340. .design-image, .trending-image, .brand-image {
  3341. width: 100%;
  3342. height: 100%;
  3343. object-fit: cover;
  3344. }
  3345. .design-overlay {
  3346. position: absolute;
  3347. top: 0;
  3348. left: 0;
  3349. right: 0;
  3350. bottom: 0;
  3351. background: rgba(0,0,0,0.7);
  3352. color: white;
  3353. display: flex;
  3354. align-items: center;
  3355. justify-content: center;
  3356. opacity: 0;
  3357. transition: opacity 0.3s ease;
  3358. }
  3359. .design-item:hover .design-overlay {
  3360. opacity: 1;
  3361. }
  3362. .preview-btn {
  3363. padding: 6px 12px;
  3364. background: #667eea;
  3365. border-radius: 6px;
  3366. font-size: 12px;
  3367. font-weight: 600;
  3368. }
  3369. .design-info, .trending-info, .brand-item-info {
  3370. padding: 12px;
  3371. }
  3372. .design-name, .trending-name, .item-name {
  3373. font-weight: 600;
  3374. font-size: 13px;
  3375. margin-bottom: 4px;
  3376. }
  3377. .design-meta, .trending-author {
  3378. font-size: 11px;
  3379. color: #666;
  3380. }
  3381. .trending-stats {
  3382. position: absolute;
  3383. top: 8px;
  3384. right: 8px;
  3385. display: flex;
  3386. gap: 8px;
  3387. }
  3388. .stat {
  3389. background: rgba(0,0,0,0.7);
  3390. color: white;
  3391. padding: 4px 6px;
  3392. border-radius: 4px;
  3393. font-size: 10px;
  3394. }
  3395. .brand-tag {
  3396. position: absolute;
  3397. top: 8px;
  3398. left: 8px;
  3399. background: #ff6b6b;
  3400. color: white;
  3401. padding: 4px 8px;
  3402. border-radius: 4px;
  3403. font-size: 10px;
  3404. font-weight: 600;
  3405. }
  3406. .item-price {
  3407. color: #ff6b6b;
  3408. font-weight: 700;
  3409. font-size: 12px;
  3410. }
  3411. .trending-filter {
  3412. margin-bottom: 20px;
  3413. }
  3414. .filter-select {
  3415. padding: 8px 12px;
  3416. border: 1px solid #dee2e6;
  3417. border-radius: 6px;
  3418. background: white;
  3419. font-size: 14px;
  3420. }
  3421. .brand-collection {
  3422. margin-bottom: 25px;
  3423. }
  3424. .brand-header {
  3425. display: flex;
  3426. align-items: center;
  3427. gap: 15px;
  3428. margin-bottom: 20px;
  3429. padding: 15px;
  3430. background: #f8f9fa;
  3431. border-radius: 12px;
  3432. }
  3433. .brand-logo {
  3434. font-size: 32px;
  3435. }
  3436. .brand-name {
  3437. font-weight: 700;
  3438. font-size: 16px;
  3439. margin-bottom: 4px;
  3440. }
  3441. .brand-desc {
  3442. font-size: 12px;
  3443. color: #666;
  3444. }
  3445. .clothing-actions, .fitting-actions {
  3446. display: flex;
  3447. justify-content: space-between;
  3448. margin-top: 25px;
  3449. }
  3450. .clothing-btn, .fitting-btn {
  3451. padding: 12px 24px;
  3452. border: 1px solid #dee2e6;
  3453. border-radius: 8px;
  3454. background: white;
  3455. cursor: pointer;
  3456. font-weight: 600;
  3457. transition: all 0.3s ease;
  3458. }
  3459. .clothing-btn.next, .fitting-btn.next {
  3460. background: #28a745;
  3461. color: white;
  3462. border-color: #28a745;
  3463. }
  3464. .clothing-btn.back, .fitting-btn.back {
  3465. background: #6c757d;
  3466. color: white;
  3467. border-color: #6c757d;
  3468. }
  3469. /* 试衣展示系统样式 */
  3470. .fitting-display {
  3471. margin-bottom: 30px;
  3472. }
  3473. .fitting-viewport {
  3474. height: 400px;
  3475. background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  3476. border-radius: 15px;
  3477. position: relative;
  3478. overflow: hidden;
  3479. display: flex;
  3480. align-items: center;
  3481. justify-content: center;
  3482. }
  3483. .user-photo-layer, .clothing-layer {
  3484. position: absolute;
  3485. top: 0;
  3486. left: 0;
  3487. right: 0;
  3488. bottom: 0;
  3489. display: flex;
  3490. align-items: center;
  3491. justify-content: center;
  3492. }
  3493. .photo-placeholder, .clothing-placeholder {
  3494. font-size: 16px;
  3495. color: #666;
  3496. background: rgba(255,255,255,0.8);
  3497. padding: 20px;
  3498. border-radius: 12px;
  3499. text-align: center;
  3500. }
  3501. .fitting-indicators {
  3502. position: absolute;
  3503. bottom: 20px;
  3504. left: 20px;
  3505. display: flex;
  3506. flex-direction: column;
  3507. gap: 10px;
  3508. }
  3509. .fit-indicator {
  3510. display: flex;
  3511. align-items: center;
  3512. gap: 8px;
  3513. background: rgba(255,255,255,0.9);
  3514. padding: 8px 12px;
  3515. border-radius: 8px;
  3516. font-size: 12px;
  3517. }
  3518. .fit-indicator.active {
  3519. background: rgba(102, 126, 234, 0.9);
  3520. color: white;
  3521. }
  3522. .indicator-icon {
  3523. font-size: 14px;
  3524. }
  3525. /* 交互控制面板样式 */
  3526. .interaction-panel {
  3527. background: #f8f9fa;
  3528. border-radius: 15px;
  3529. padding: 20px;
  3530. margin-bottom: 25px;
  3531. }
  3532. .control-sections {
  3533. display: grid;
  3534. grid-template-columns: 1fr;
  3535. gap: 20px;
  3536. }
  3537. .control-section {
  3538. background: white;
  3539. padding: 15px;
  3540. border-radius: 12px;
  3541. }
  3542. .section-title {
  3543. font-weight: 600;
  3544. font-size: 14px;
  3545. margin-bottom: 15px;
  3546. color: #333;
  3547. }
  3548. .rotation-controls, .lighting-controls, .compare-controls {
  3549. display: flex;
  3550. justify-content: center;
  3551. gap: 10px;
  3552. flex-wrap: wrap;
  3553. }
  3554. .rotation-btn, .lighting-btn, .compare-btn {
  3555. padding: 8px 16px;
  3556. border: 1px solid #dee2e6;
  3557. border-radius: 8px;
  3558. background: white;
  3559. cursor: pointer;
  3560. transition: all 0.3s ease;
  3561. font-size: 12px;
  3562. display: flex;
  3563. align-items: center;
  3564. gap: 6px;
  3565. }
  3566. .rotation-btn:hover, .lighting-btn:hover, .compare-btn:hover {
  3567. background: #f8f9fa;
  3568. transform: translateY(-2px);
  3569. }
  3570. .lighting-btn.active, .compare-btn.active {
  3571. background: #667eea;
  3572. color: white;
  3573. border-color: #667eea;
  3574. }
  3575. .gesture-hint {
  3576. text-align: center;
  3577. font-size: 11px;
  3578. color: #666;
  3579. margin-top: 10px;
  3580. }
  3581. .light-icon, .compare-icon {
  3582. font-size: 14px;
  3583. }
  3584. /* 输出功能样式 */
  3585. .output-panel {
  3586. background: white;
  3587. border-radius: 15px;
  3588. padding: 20px;
  3589. border: 2px solid #e9ecef;
  3590. margin-bottom: 25px;
  3591. }
  3592. .output-actions {
  3593. display: grid;
  3594. grid-template-columns: 1fr;
  3595. gap: 15px;
  3596. }
  3597. .output-btn {
  3598. display: flex;
  3599. align-items: center;
  3600. gap: 15px;
  3601. padding: 15px;
  3602. border: 2px solid #e9ecef;
  3603. border-radius: 12px;
  3604. background: white;
  3605. cursor: pointer;
  3606. transition: all 0.3s ease;
  3607. }
  3608. .output-btn:hover {
  3609. border-color: #667eea;
  3610. background: #f8f9ff;
  3611. transform: translateY(-2px);
  3612. }
  3613. .output-btn.save {
  3614. border-color: #28a745;
  3615. }
  3616. .output-btn.share {
  3617. border-color: #17a2b8;
  3618. }
  3619. .output-btn.purchase {
  3620. border-color: #ff6b6b;
  3621. }
  3622. .output-icon {
  3623. font-size: 24px;
  3624. flex-shrink: 0;
  3625. }
  3626. .output-text {
  3627. flex: 1;
  3628. }
  3629. .output-title {
  3630. font-weight: 600;
  3631. font-size: 14px;
  3632. margin-bottom: 4px;
  3633. }
  3634. .output-desc {
  3635. font-size: 12px;
  3636. color: #666;
  3637. }
  3638. .fitting-btn.retry {
  3639. background: #ffc107;
  3640. color: #212529;
  3641. border-color: #ffc107;
  3642. }
  3643. /* 移动端适配 */
  3644. @media (max-width: 768px) {
  3645. .fitting-flow-nav {
  3646. padding: 0 10px;
  3647. }
  3648. .flow-step {
  3649. margin: 0 5px;
  3650. padding: 10px 15px;
  3651. min-width: 60px;
  3652. }
  3653. .step-icon {
  3654. font-size: 16px;
  3655. }
  3656. .step-text {
  3657. font-size: 10px;
  3658. }
  3659. .upload-methods {
  3660. grid-template-columns: 1fr;
  3661. }
  3662. .design-grid, .trending-grid, .brand-grid {
  3663. grid-template-columns: repeat(2, 1fr);
  3664. }
  3665. .control-sections {
  3666. grid-template-columns: 1fr;
  3667. }
  3668. .rotation-controls, .lighting-controls, .compare-controls {
  3669. justify-content: space-around;
  3670. }
  3671. .clothing-actions, .fitting-actions {
  3672. flex-direction: column;
  3673. gap: 10px;
  3674. }
  3675. .clothing-btn, .fitting-btn {
  3676. width: 100%;
  3677. }
  3678. }
  3679. </style>
  3680. </head>
  3681. <body>
  3682. <!-- 登录注册欢迎页面 -->
  3683. <div id="auth-screen" class="auth-screen">
  3684. <div class="auth-container">
  3685. <div class="auth-header">
  3686. <div class="brand-logo">
  3687. <div class="logo-icon">✨</div>
  3688. <h1>FashionCraft</h1>
  3689. <p>让创意穿在身上</p>
  3690. </div>
  3691. </div>
  3692. <div class="auth-content">
  3693. <div class="welcome-message">
  3694. <h2>欢迎来到时尚设计世界</h2>
  3695. <p>登录开启您的专属设计之旅</p>
  3696. </div>
  3697. <div class="auth-actions">
  3698. <button class="auth-btn primary" onclick="showLoginForm()">
  3699. <span class="btn-icon">🔑</span>
  3700. <span>立即登录</span>
  3701. </button>
  3702. <button class="auth-btn secondary" onclick="showRegisterForm()">
  3703. <span class="btn-icon">✍️</span>
  3704. <span>注册账户</span>
  3705. </button>
  3706. </div>
  3707. <div class="auth-features">
  3708. <div class="feature-item">
  3709. <div class="feature-icon">🎨</div>
  3710. <div class="feature-text">
  3711. <div class="feature-title">3D设计中心</div>
  3712. <div class="feature-desc">专业级颜色DIY设计器</div>
  3713. </div>
  3714. </div>
  3715. <div class="feature-item">
  3716. <div class="feature-icon">🤖</div>
  3717. <div class="feature-text">
  3718. <div class="feature-title">AI智能推荐</div>
  3719. <div class="feature-desc">个性化搭配建议</div>
  3720. </div>
  3721. </div>
  3722. <div class="feature-item">
  3723. <div class="feature-icon">👕</div>
  3724. <div class="feature-text">
  3725. <div class="feature-title">3D试衣间</div>
  3726. <div class="feature-desc">虚拟试穿体验</div>
  3727. </div>
  3728. </div>
  3729. </div>
  3730. </div>
  3731. <div class="auth-footer">
  3732. <div class="version-info">v1.0.0</div>
  3733. <div class="copyright">© 2025 FashionCraft</div>
  3734. </div>
  3735. </div>
  3736. </div>
  3737. <!-- 主要应用容器 -->
  3738. <div class="app-container" id="main-app" style="display: none;">
  3739. <!-- 首页 -->
  3740. <div id="home-page" class="page">
  3741. <header class="header">
  3742. <div class="header-content">
  3743. <h1>FashionCraft</h1>
  3744. <p>让创意穿在身上</p>
  3745. </div>
  3746. </header>
  3747. <main class="main-content">
  3748. <!-- 轮播区域 -->
  3749. <section class="banner-section">
  3750. <div class="banner-slider" id="bannerSlider">
  3751. <div class="banner-slide">
  3752. <div>
  3753. <div style="font-size: 24px; margin-bottom: 10px;">🎨</div>
  3754. <div>春季新品发布</div>
  3755. <div style="font-size: 14px; opacity: 0.8;">个性化设计,独一无二</div>
  3756. </div>
  3757. </div>
  3758. <div class="banner-slide" style="background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);">
  3759. <div>
  3760. <div style="font-size: 24px; margin-bottom: 10px;">✨</div>
  3761. <div>AI智能搭配</div>
  3762. <div style="font-size: 14px; opacity: 0.8;">科技赋能时尚创意</div>
  3763. </div>
  3764. </div>
  3765. <div class="banner-slide" style="background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);">
  3766. <div>
  3767. <div style="font-size: 24px; margin-bottom: 10px;">🏆</div>
  3768. <div>设计大赛进行中</div>
  3769. <div style="font-size: 14px; opacity: 0.8;">万元奖金等你来拿</div>
  3770. </div>
  3771. </div>
  3772. </div>
  3773. <div class="banner-indicators">
  3774. <div class="indicator active" data-slide="0"></div>
  3775. <div class="indicator" data-slide="1"></div>
  3776. <div class="indicator" data-slide="2"></div>
  3777. </div>
  3778. </section>
  3779. <!-- 快速设计入口 -->
  3780. <section class="quick-design" onclick="showDesignModal()">
  3781. <h2>开始设计</h2>
  3782. <p>点击开启你的创意之旅</p>
  3783. </section>
  3784. <!-- 热门作品 -->
  3785. <section class="popular-works">
  3786. <h3 class="section-title">热门作品</h3>
  3787. <div class="works-grid">
  3788. <div class="work-item" onclick="showWorkDetail('森系小清新')">
  3789. <div class="work-image">🌿</div>
  3790. <div class="work-info">
  3791. <div class="work-title">森系小清新</div>
  3792. <div class="work-stats">
  3793. <span>❤️ 2.3k</span>
  3794. <span>💬 186</span>
  3795. </div>
  3796. </div>
  3797. </div>
  3798. <div class="work-item" onclick="showWorkDetail('复古摩登')">
  3799. <div class="work-image" style="background: linear-gradient(45deg, #ffd89b 0%, #19547b 100%);">🎭</div>
  3800. <div class="work-info">
  3801. <div class="work-title">复古摩登</div>
  3802. <div class="work-stats">
  3803. <span>❤️ 1.8k</span>
  3804. <span>💬 142</span>
  3805. </div>
  3806. </div>
  3807. </div>
  3808. <div class="work-item" onclick="showWorkDetail('未来科技')">
  3809. <div class="work-image" style="background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);">🚀</div>
  3810. <div class="work-info">
  3811. <div class="work-title">未来科技</div>
  3812. <div class="work-stats">
  3813. <span>❤️ 3.1k</span>
  3814. <span>💬 256</span>
  3815. </div>
  3816. </div>
  3817. </div>
  3818. <div class="work-item" onclick="showWorkDetail('简约现代')">
  3819. <div class="work-image" style="background: linear-gradient(45deg, #ff9a9e 0%, #fecfef 100%);">🏛️</div>
  3820. <div class="work-info">
  3821. <div class="work-title">简约现代</div>
  3822. <div class="work-stats">
  3823. <span>❤️ 1.5k</span>
  3824. <span>💬 98</span>
  3825. </div>
  3826. </div>
  3827. </div>
  3828. </div>
  3829. </section>
  3830. <!-- AI推荐引擎入口 -->
  3831. <section class="ai-recommend-engine">
  3832. <div class="ai-engine-card">
  3833. <div class="ai-engine-header">
  3834. <div class="ai-brand">
  3835. <span class="ai-logo">🤖</span>
  3836. <div class="ai-brand-text">
  3837. <h3>AI时尚顾问 <span style="font-size: 10px; background: linear-gradient(45deg, #667eea, #764ba2); padding: 1px 4px; border-radius: 6px; color: white;">DeepSeek</span></h3>
  3838. <p>专业搭配 · 智能推荐</p>
  3839. </div>
  3840. </div>
  3841. <div class="ai-status">
  3842. <span class="status-dot"></span>
  3843. <span class="status-text">在线</span>
  3844. </div>
  3845. </div>
  3846. <div class="ai-quick-actions">
  3847. <div class="quick-action" onclick="openAIChat('occasion')">
  3848. <span class="action-icon">🎯</span>
  3849. <span class="action-text">场合搭配</span>
  3850. </div>
  3851. <div class="quick-action" onclick="openAIChat('color')">
  3852. <span class="action-icon">🎨</span>
  3853. <span class="action-text">配色建议</span>
  3854. </div>
  3855. <div class="quick-action" onclick="openAIChat('style')">
  3856. <span class="action-icon">✨</span>
  3857. <span class="action-text">风格分析</span>
  3858. </div>
  3859. <div class="quick-action" onclick="openAIChat('free')">
  3860. <span class="action-icon">💬</span>
  3861. <span class="action-text">自由对话</span>
  3862. </div>
  3863. </div>
  3864. </div>
  3865. </section>
  3866. </main>
  3867. </div>
  3868. <!-- 设计中心页面 -->
  3869. <div id="design-page" class="page design-tools">
  3870. <header class="header">
  3871. <div class="header-content">
  3872. <h1>3D设计中心</h1>
  3873. <p>专业级颜色DIY设计器</p>
  3874. </div>
  3875. </header>
  3876. <main class="main-content">
  3877. <!-- 实时3D预览系统 -->
  3878. <div class="design-preview-system">
  3879. <div class="preview-container">
  3880. <div class="preview-3d-enhanced">
  3881. <div class="model-3d-wrapper">
  3882. <div class="clothing-preview" id="main3DModel">
  3883. <div class="clothing-layer" id="layer-s1">
  3884. <img src="切片图共7个/切片图共7个/蓝色/S1.png" alt="S1部位" class="part-image" data-part="s1">
  3885. </div>
  3886. <div class="clothing-layer" id="layer-t1">
  3887. <img src="切片图共7个/切片图共7个/蓝色/T1.png" alt="T1部位" class="part-image" data-part="t1">
  3888. </div>
  3889. <div class="clothing-layer" id="layer-y1">
  3890. <img src="切片图共7个/切片图共7个/蓝色/Y1.png" alt="Y1部位" class="part-image" data-part="y1">
  3891. </div>
  3892. <div class="clothing-layer" id="layer-z1">
  3893. <img src="切片图共7个/切片图共7个/蓝色/Z1.png" alt="Z1部位" class="part-image" data-part="z1">
  3894. </div>
  3895. </div>
  3896. <div class="model-highlights" id="modelHighlights"></div>
  3897. </div>
  3898. <!-- 3D控制面板 -->
  3899. <div class="preview-controls">
  3900. <div class="control-group">
  3901. <button class="control-btn" onclick="rotateModel('left')" title="向左旋转">↻</button>
  3902. <button class="control-btn" onclick="rotateModel('right')" title="向右旋转">↺</button>
  3903. <button class="control-btn" onclick="resetModelView()" title="重置视角">⌂</button>
  3904. </div>
  3905. </div>
  3906. </div>
  3907. </div>
  3908. </div>
  3909. <!-- 3D分区控制面板 -->
  3910. <div class="zone-control-panel">
  3911. <div class="panel-header">
  3912. <h3>分区控制面板</h3>
  3913. <button class="expand-btn" onclick="toggleZonePanel()">⌄</button>
  3914. </div>
  3915. <div class="panel-content">
  3916. <!-- 部位选择器(胶囊式Tab) -->
  3917. <div class="body-part-selector">
  3918. <div class="part-tabs">
  3919. <button class="part-tab active" data-part="overall" onclick="selectBodyPart('overall')">
  3920. <span class="tab-icon">🎯</span>
  3921. <span class="tab-text">整体</span>
  3922. </button>
  3923. <button class="part-tab" data-part="s1" onclick="selectBodyPart('s1')">
  3924. <span class="tab-icon">👔</span>
  3925. <span class="tab-text">S1部位</span>
  3926. </button>
  3927. <button class="part-tab" data-part="t1" onclick="selectBodyPart('t1')">
  3928. <span class="tab-icon">👕</span>
  3929. <span class="tab-text">T1部位</span>
  3930. </button>
  3931. <button class="part-tab" data-part="y1" onclick="selectBodyPart('y1')">
  3932. <span class="tab-icon">🎽</span>
  3933. <span class="tab-text">Y1部位</span>
  3934. </button>
  3935. <button class="part-tab" data-part="z1" onclick="selectBodyPart('z1')">
  3936. <span class="tab-icon">🧥</span>
  3937. <span class="tab-text">Z1部位</span>
  3938. </button>
  3939. </div>
  3940. </div>
  3941. </div>
  3942. </div>
  3943. <!-- 色盘管理系统 -->
  3944. <div class="color-management-system">
  3945. <div class="color-system-header">
  3946. <h3>智能色盘系统</h3>
  3947. <div class="color-actions">
  3948. <button class="action-btn" onclick="syncColorToAll()" title="同步当前色到所有部位">🔄</button>
  3949. <button class="action-btn" onclick="showColorHistory()" title="查看配色历史">📚</button>
  3950. <button class="action-btn" onclick="saveColorScheme()" title="保存配色方案">💾</button>
  3951. </div>
  3952. </div>
  3953. <!-- 分区色盘记忆 -->
  3954. <div class="zone-color-memory">
  3955. <div class="current-part-info">
  3956. <span class="part-label">当前部位:</span>
  3957. <span class="part-name" id="currentPartName">整体</span>
  3958. <span class="color-indicator" id="currentPartColor" style="background: #ff6b6b;"></span>
  3959. </div>
  3960. </div>
  3961. <!-- 主色盘 -->
  3962. <div class="master-color-picker">
  3963. <div class="color-picker-section">
  3964. <h4>基础色盘</h4>
  3965. <div class="color-palette enhanced-palette">
  3966. <!-- 原有颜色 -->
  3967. <div class="color-swatch" style="background: #3498db" onclick="selectClothingColor('蓝色')" data-color="蓝色" title="蓝色"></div>
  3968. <div class="color-swatch" style="background: #e91e63" onclick="selectClothingColor('粉色')" data-color="粉色" title="粉色"></div>
  3969. <div class="color-swatch" style="background: #8bc34a" onclick="selectClothingColor('牛油果绿')" data-color="牛油果绿" title="牛油果绿"></div>
  3970. <div class="color-swatch" style="background: #ffffff; border: 2px solid #ddd" onclick="selectClothingColor('白色')" data-color="白色" title="白色"></div>
  3971. <div class="color-swatch" style="background: #2c3e50" onclick="selectClothingColor('黑色')" data-color="黑色" title="黑色"></div>
  3972. <div class="color-swatch" style="background: #ff9800" onclick="selectClothingColor('橘色')" data-color="橘色" title="橘色"></div>
  3973. <div class="color-swatch" style="background: #9e9e9e" onclick="selectClothingColor('利灰')" data-color="利灰" title="利灰"></div>
  3974. <!-- 新增颜色 -->
  3975. <div class="color-swatch" style="background: #1e40af" onclick="selectClothingColor('宝蓝色')" data-color="宝蓝色" title="宝蓝色"></div>
  3976. <div class="color-swatch" style="background: #d2b48c" onclick="selectClothingColor('浅驼色')" data-color="浅驼色" title="浅驼色"></div>
  3977. <div class="color-swatch" style="background: #9ca3af" onclick="selectClothingColor('测试色')" data-color="测试色" title="测试色"></div>
  3978. <div class="color-swatch" style="background: #374151" onclick="selectClothingColor('深灰绿')" data-color="深灰绿" title="深灰绿"></div>
  3979. <div class="color-swatch" style="background: #581c87" onclick="selectClothingColor('深紫色')" data-color="深紫色" title="深紫色"></div>
  3980. <div class="color-swatch" style="background: #14532d" onclick="selectClothingColor('深绿色')" data-color="深绿色" title="深绿色"></div>
  3981. <div class="color-swatch" style="background: #dc2626" onclick="selectClothingColor('真朱')" data-color="真朱" title="真朱"></div>
  3982. <div class="color-swatch" style="background: #fbbf24" onclick="selectClothingColor('睿智金')" data-color="睿智金" title="睿智金"></div>
  3983. <div class="color-swatch" style="background: #ef4444" onclick="selectClothingColor('红色')" data-color="红色" title="红色"></div>
  3984. <div class="color-swatch" style="background: #84cc16" onclick="selectClothingColor('萌萌绿')" data-color="萌萌绿" title="萌萌绿"></div>
  3985. <div class="color-swatch" style="background: #0891b2" onclick="selectClothingColor('蒂芙尼蓝')" data-color="蒂芙尼蓝" title="蒂芙尼蓝"></div>
  3986. <div class="color-swatch" style="background: #3b82f6" onclick="selectClothingColor('长春花蓝')" data-color="长春花蓝" title="长春花蓝"></div>
  3987. <div class="color-swatch" style="background: #6b46c1" onclick="selectClothingColor('青紫')" data-color="青紫" title="青紫"></div>
  3988. <div class="color-swatch" style="background: #eab308" onclick="selectClothingColor('靓丽黄')" data-color="靓丽黄" title="靓丽黄"></div>
  3989. </div>
  3990. </div>
  3991. <!-- 自定义颜色 -->
  3992. <div class="color-picker-section">
  3993. <h4>自定义颜色</h4>
  3994. <div class="custom-color-controls">
  3995. <input type="color" id="customColorPicker" value="#ff6b6b" onchange="selectCustomColor(this.value)">
  3996. <button class="add-custom-btn" onclick="addCustomColor()">添加到色盘</button>
  3997. </div>
  3998. </div>
  3999. </div>
  4000. <!-- 历史配色库 -->
  4001. <div class="color-history-section" id="colorHistorySection" style="display: none;">
  4002. <h4>配色历史</h4>
  4003. <div class="history-schemes">
  4004. <div class="scheme-item" onclick="loadColorScheme('scheme1')">
  4005. <div class="scheme-preview">
  4006. <div class="scheme-color" style="background: #ff6b6b;"></div>
  4007. <div class="scheme-color" style="background: #4ecdc4;"></div>
  4008. <div class="scheme-color" style="background: #ffeaa7;"></div>
  4009. </div>
  4010. <span class="scheme-name">夏日活力</span>
  4011. </div>
  4012. <div class="scheme-item" onclick="loadColorScheme('scheme2')">
  4013. <div class="scheme-preview">
  4014. <div class="scheme-color" style="background: #667eea;"></div>
  4015. <div class="scheme-color" style="background: #764ba2;"></div>
  4016. <div class="scheme-color" style="background: #a29bfe;"></div>
  4017. </div>
  4018. <span class="scheme-name">深海紫韵</span>
  4019. </div>
  4020. </div>
  4021. </div>
  4022. </div>
  4023. <!-- 高级定制工具 -->
  4024. <div class="advanced-tools">
  4025. <div class="tools-header">
  4026. <h3>高级定制</h3>
  4027. </div>
  4028. <div class="advanced-tool-grid">
  4029. <div class="advanced-tool-card" onclick="openAdvancedEmbroidery()">
  4030. <span class="tool-icon">🧵</span>
  4031. <div class="tool-content">
  4032. <div class="tool-title">刺绣编辑器</div>
  4033. <div class="tool-desc">支持按部位精确定位</div>
  4034. </div>
  4035. </div>
  4036. <div class="advanced-tool-card" onclick="openTextureSystem()">
  4037. <span class="tool-icon">🎨</span>
  4038. <div class="tool-content">
  4039. <div class="tool-title">贴图系统</div>
  4040. <div class="tool-desc">可指定应用区域</div>
  4041. </div>
  4042. </div>
  4043. <div class="advanced-tool-card" onclick="openPatternLibrary()">
  4044. <span class="tool-icon">✨</span>
  4045. <div class="tool-content">
  4046. <div class="tool-title">图案库</div>
  4047. <div class="tool-desc">海量设计素材</div>
  4048. </div>
  4049. </div>
  4050. <div class="advanced-tool-card" onclick="openAIDesigner()">
  4051. <span class="tool-icon">🤖</span>
  4052. <div class="tool-content">
  4053. <div class="tool-title">AI设计师</div>
  4054. <div class="tool-desc">智能配色建议</div>
  4055. </div>
  4056. </div>
  4057. </div>
  4058. </div>
  4059. </main>
  4060. </div>
  4061. <!-- 3D试衣间页面 -->
  4062. <div id="ar-page" class="page" style="display: none;">
  4063. <header class="header">
  4064. <div class="header-content">
  4065. <h1>3D试衣间</h1>
  4066. <p>智能试穿,完美贴合</p>
  4067. </div>
  4068. </header>
  4069. <main class="main-content">
  4070. <!-- 核心流程导航 -->
  4071. <div class="fitting-flow-nav">
  4072. <div class="flow-step active" data-step="upload">
  4073. <div class="step-icon">📷</div>
  4074. <div class="step-text">照片上传</div>
  4075. </div>
  4076. <div class="flow-step" data-step="clothing">
  4077. <div class="step-icon">👕</div>
  4078. <div class="step-text">服装选择</div>
  4079. </div>
  4080. <div class="flow-step" data-step="fitting">
  4081. <div class="step-icon">✨</div>
  4082. <div class="step-text">试衣展示</div>
  4083. </div>
  4084. </div>
  4085. <!-- 步骤1: 照片上传入口 -->
  4086. <div class="fitting-step" id="upload-step">
  4087. <div class="step-container">
  4088. <h3 class="step-title">📷 照片上传入口</h3>
  4089. <!-- 上传方式选择 -->
  4090. <div class="upload-methods">
  4091. <div class="upload-method active" data-method="camera" onclick="selectUploadMethod('camera')">
  4092. <div class="method-icon">📹</div>
  4093. <div class="method-title">拍照模式</div>
  4094. <div class="method-desc">实时摄像头拍摄</div>
  4095. </div>
  4096. <div class="upload-method" data-method="gallery" onclick="selectUploadMethod('gallery')">
  4097. <div class="method-icon">🖼️</div>
  4098. <div class="method-title">相册选择</div>
  4099. <div class="method-desc">支持裁剪调整</div>
  4100. </div>
  4101. </div>
  4102. <!-- 拍照模式界面 -->
  4103. <div class="camera-interface" id="camera-mode">
  4104. <div class="camera-preview">
  4105. <div class="camera-placeholder">
  4106. <div class="camera-icon">📷</div>
  4107. <div class="camera-text">点击启动摄像头</div>
  4108. <div class="camera-hint">请确保良好的光线条件</div>
  4109. </div>
  4110. <!-- 姿势引导框 -->
  4111. <div class="pose-guide">
  4112. <div class="guide-silhouette">🧑‍🦱</div>
  4113. <div class="guide-text">请保持正面站立姿势</div>
  4114. </div>
  4115. </div>
  4116. <div class="camera-controls">
  4117. <button class="camera-btn" onclick="startCamera()">启动摄像头</button>
  4118. <button class="camera-btn capture" onclick="capturePhoto()">拍摄照片</button>
  4119. <button class="camera-btn switch" onclick="switchCamera()">切换摄像头</button>
  4120. </div>
  4121. </div>
  4122. <!-- 相册选择界面 -->
  4123. <div class="gallery-interface" id="gallery-mode" style="display: none;">
  4124. <div class="gallery-upload">
  4125. <input type="file" id="photo-upload" accept="image/*" style="display: none;" onchange="handlePhotoUpload(this)">
  4126. <div class="upload-zone" onclick="document.getElementById('photo-upload').click()">
  4127. <div class="upload-icon">📁</div>
  4128. <div class="upload-text">选择照片</div>
  4129. <div class="upload-hint">支持JPG、PNG格式</div>
  4130. </div>
  4131. </div>
  4132. <!-- 图片裁剪区域 -->
  4133. <div class="crop-area" id="crop-area" style="display: none;">
  4134. <div class="crop-container">
  4135. <canvas id="crop-canvas"></canvas>
  4136. <div class="crop-overlay"></div>
  4137. </div>
  4138. <div class="crop-controls">
  4139. <button class="crop-btn" onclick="resetCrop()">重置</button>
  4140. <button class="crop-btn confirm" onclick="confirmCrop()">确认裁剪</button>
  4141. </div>
  4142. </div>
  4143. </div>
  4144. <!-- 姿势校准系统 -->
  4145. <div class="pose-calibration" id="pose-calibration" style="display: none;">
  4146. <h4>🎯 姿势校准</h4>
  4147. <div class="calibration-display">
  4148. <div class="body-keypoints">
  4149. <div class="keypoint head" data-point="head">头部</div>
  4150. <div class="keypoint shoulder-left" data-point="shoulder-left">左肩</div>
  4151. <div class="keypoint shoulder-right" data-point="shoulder-right">右肩</div>
  4152. <div class="keypoint waist" data-point="waist">腰部</div>
  4153. <div class="keypoint hip" data-point="hip">臀部</div>
  4154. </div>
  4155. <div class="calibration-status">
  4156. <div class="status-item">
  4157. <span class="status-icon">✅</span>
  4158. <span>人体识别成功</span>
  4159. </div>
  4160. <div class="status-item">
  4161. <span class="status-icon">✅</span>
  4162. <span>关键点定位完成</span>
  4163. </div>
  4164. <div class="status-item">
  4165. <span class="status-icon">⏳</span>
  4166. <span>身形分析中...</span>
  4167. </div>
  4168. </div>
  4169. </div>
  4170. <div class="calibration-actions">
  4171. <button class="calib-btn" onclick="recalibrate()">重新校准</button>
  4172. <button class="calib-btn next" onclick="nextStep('clothing')">下一步:选择服装</button>
  4173. </div>
  4174. </div>
  4175. </div>
  4176. </div>
  4177. <!-- 步骤2: 服装选择器 -->
  4178. <div class="fitting-step" id="clothing-step" style="display: none;">
  4179. <div class="step-container">
  4180. <h3 class="step-title">👕 服装选择器</h3>
  4181. <!-- 服装分类标签 -->
  4182. <div class="clothing-tabs">
  4183. <div class="clothing-tab active" data-tab="my-designs" onclick="switchClothingTab('my-designs')">
  4184. <span class="tab-icon">🎨</span>
  4185. <span class="tab-text">我的设计</span>
  4186. <span class="tab-count">12</span>
  4187. </div>
  4188. <div class="clothing-tab" data-tab="community" onclick="switchClothingTab('community')">
  4189. <span class="tab-icon">🔥</span>
  4190. <span class="tab-text">社区热门</span>
  4191. <span class="tab-count">156</span>
  4192. </div>
  4193. <div class="clothing-tab" data-tab="brands" onclick="switchClothingTab('brands')">
  4194. <span class="tab-icon">🏷️</span>
  4195. <span class="tab-text">品牌合作</span>
  4196. <span class="tab-count">89</span>
  4197. </div>
  4198. </div>
  4199. <!-- 我的设计列表 -->
  4200. <div class="clothing-content" id="my-designs-content">
  4201. <div class="design-grid">
  4202. <div class="design-item" onclick="selectClothing('my-design-1')">
  4203. <div class="design-preview">
  4204. <img src="切片图/切片图/宝蓝色/宝蓝色.png" alt="我的设计1" class="design-image">
  4205. <div class="design-overlay">
  4206. <div class="preview-btn">预览效果</div>
  4207. </div>
  4208. </div>
  4209. <div class="design-info">
  4210. <div class="design-name">经典商务款</div>
  4211. <div class="design-meta">创建于 2024-01-15</div>
  4212. </div>
  4213. </div>
  4214. <div class="design-item" onclick="selectClothing('my-design-2')">
  4215. <div class="design-preview">
  4216. <img src="切片图/切片图/靓丽黄/靓丽黄.png" alt="我的设计2" class="design-image">
  4217. <div class="design-overlay">
  4218. <div class="preview-btn">预览效果</div>
  4219. </div>
  4220. </div>
  4221. <div class="design-info">
  4222. <div class="design-name">活力运动款</div>
  4223. <div class="design-meta">创建于 2024-01-12</div>
  4224. </div>
  4225. </div>
  4226. <div class="design-item" onclick="selectClothing('my-design-3')">
  4227. <div class="design-preview">
  4228. <img src="切片图/切片图/蒂芙尼蓝/蒂芙尼蓝.png" alt="我的设计3" class="design-image">
  4229. <div class="design-overlay">
  4230. <div class="preview-btn">预览效果</div>
  4231. </div>
  4232. </div>
  4233. <div class="design-info">
  4234. <div class="design-name">优雅晚装</div>
  4235. <div class="design-meta">创建于 2024-01-10</div>
  4236. </div>
  4237. </div>
  4238. </div>
  4239. </div>
  4240. <!-- 社区热门列表 -->
  4241. <div class="clothing-content" id="community-content" style="display: none;">
  4242. <div class="trending-filter">
  4243. <select class="filter-select">
  4244. <option>今日热门</option>
  4245. <option>本周热门</option>
  4246. <option>本月热门</option>
  4247. </select>
  4248. </div>
  4249. <div class="trending-grid">
  4250. <div class="trending-item" onclick="selectClothing('trending-1')">
  4251. <div class="trending-preview">
  4252. <img src="切片图/切片图/深紫色/深紫色.png" alt="热门设计1" class="trending-image">
  4253. <div class="trending-stats">
  4254. <span class="stat">❤️ 2.3k</span>
  4255. <span class="stat">💬 156</span>
  4256. </div>
  4257. </div>
  4258. <div class="trending-info">
  4259. <div class="trending-name">神秘紫韵</div>
  4260. <div class="trending-author">by 设计师Anna</div>
  4261. </div>
  4262. </div>
  4263. <div class="trending-item" onclick="selectClothing('trending-2')">
  4264. <div class="trending-preview">
  4265. <img src="切片图/切片图/萌萌绿/萌萌绿.png" alt="热门设计2" class="trending-image">
  4266. <div class="trending-stats">
  4267. <span class="stat">❤️ 1.8k</span>
  4268. <span class="stat">💬 89</span>
  4269. </div>
  4270. </div>
  4271. <div class="trending-info">
  4272. <div class="trending-name">春日萌动</div>
  4273. <div class="trending-author">by 创意大师Leo</div>
  4274. </div>
  4275. </div>
  4276. </div>
  4277. </div>
  4278. <!-- 品牌合作列表 -->
  4279. <div class="clothing-content" id="brands-content" style="display: none;">
  4280. <div class="brand-collection">
  4281. <div class="brand-header">
  4282. <div class="brand-logo">🏷️</div>
  4283. <div class="brand-info">
  4284. <div class="brand-name">时尚前线</div>
  4285. <div class="brand-desc">2024春季新品系列</div>
  4286. </div>
  4287. </div>
  4288. <div class="brand-grid">
  4289. <div class="brand-item" onclick="selectClothing('brand-1')">
  4290. <div class="brand-preview">
  4291. <img src="切片图/切片图/真朱/真朱.png" alt="品牌设计1" class="brand-image">
  4292. <div class="brand-tag">限量款</div>
  4293. </div>
  4294. <div class="brand-item-info">
  4295. <div class="item-name">经典红韵</div>
  4296. <div class="item-price">¥899</div>
  4297. </div>
  4298. </div>
  4299. <div class="brand-item" onclick="selectClothing('brand-2')">
  4300. <div class="brand-preview">
  4301. <img src="切片图/切片图/睿智金/睿智金.png" alt="品牌设计2" class="brand-image">
  4302. <div class="brand-tag">新品</div>
  4303. </div>
  4304. <div class="brand-item-info">
  4305. <div class="item-name">智慧金辉</div>
  4306. <div class="item-price">¥1299</div>
  4307. </div>
  4308. </div>
  4309. </div>
  4310. </div>
  4311. </div>
  4312. <div class="clothing-actions">
  4313. <button class="clothing-btn back" onclick="previousStep('upload')">上一步</button>
  4314. <button class="clothing-btn next" onclick="nextStep('fitting')">开始试穿</button>
  4315. </div>
  4316. </div>
  4317. </div>
  4318. <!-- 步骤3: 试衣展示系统 -->
  4319. <div class="fitting-step" id="fitting-step" style="display: none;">
  4320. <div class="step-container">
  4321. <h3 class="step-title">✨ 试衣展示系统</h3>
  4322. <!-- 试穿预览区域 -->
  4323. <div class="fitting-display">
  4324. <div class="fitting-viewport">
  4325. <div class="user-photo-layer">
  4326. <div class="photo-placeholder">用户照片将显示在这里</div>
  4327. </div>
  4328. <div class="clothing-layer">
  4329. <div class="clothing-placeholder">选中的服装将叠加在这里</div>
  4330. </div>
  4331. <!-- 智能贴合引擎指示器 -->
  4332. <div class="fitting-indicators">
  4333. <div class="fit-indicator active" data-status="processing">
  4334. <span class="indicator-icon">🔄</span>
  4335. <span class="indicator-text">布料物理模拟</span>
  4336. </div>
  4337. <div class="fit-indicator" data-status="completed">
  4338. <span class="indicator-icon">✅</span>
  4339. <span class="indicator-text">身形适配完成</span>
  4340. </div>
  4341. </div>
  4342. </div>
  4343. </div>
  4344. <!-- 交互控制面板 -->
  4345. <div class="interaction-panel">
  4346. <h4>🎮 交互控制面板</h4>
  4347. <div class="control-sections">
  4348. <!-- 旋转查看 -->
  4349. <div class="control-section">
  4350. <div class="section-title">旋转查看</div>
  4351. <div class="rotation-controls">
  4352. <button class="rotation-btn" onclick="rotateFitting('left')">⬅️ 左转</button>
  4353. <button class="rotation-btn" onclick="rotateFitting('reset')">🎯 正面</button>
  4354. <button class="rotation-btn" onclick="rotateFitting('right')">右转 ➡️</button>
  4355. </div>
  4356. <div class="gesture-hint">💡 支持手势滑动控制</div>
  4357. </div>
  4358. <!-- 光照调节 -->
  4359. <div class="control-section">
  4360. <div class="section-title">光照调节</div>
  4361. <div class="lighting-controls">
  4362. <button class="lighting-btn active" onclick="setFittingLight('natural')">
  4363. <span class="light-icon">☀️</span>
  4364. <span>自然光</span>
  4365. </button>
  4366. <button class="lighting-btn" onclick="setFittingLight('indoor')">
  4367. <span class="light-icon">💡</span>
  4368. <span>室内光</span>
  4369. </button>
  4370. <button class="lighting-btn" onclick="setFittingLight('studio')">
  4371. <span class="light-icon">🎬</span>
  4372. <span>摄影光</span>
  4373. </button>
  4374. </div>
  4375. </div>
  4376. <!-- 对比模式 -->
  4377. <div class="control-section">
  4378. <div class="section-title">对比模式</div>
  4379. <div class="compare-controls">
  4380. <button class="compare-btn active" onclick="toggleCompare('split')">
  4381. <span class="compare-icon">⚖️</span>
  4382. <span>左右对比</span>
  4383. </button>
  4384. <button class="compare-btn" onclick="toggleCompare('overlay')">
  4385. <span class="compare-icon">🔄</span>
  4386. <span>叠加对比</span>
  4387. </button>
  4388. </div>
  4389. </div>
  4390. </div>
  4391. </div>
  4392. <!-- 输出功能 -->
  4393. <div class="output-panel">
  4394. <h4>💾 输出功能</h4>
  4395. <div class="output-actions">
  4396. <button class="output-btn save" onclick="saveImageCard()">
  4397. <span class="output-icon">💳</span>
  4398. <div class="output-text">
  4399. <div class="output-title">保存形象卡</div>
  4400. <div class="output-desc">含服装信息和试穿效果</div>
  4401. </div>
  4402. </button>
  4403. <button class="output-btn share" onclick="shareToCommunity()">
  4404. <span class="output-icon">🌐</span>
  4405. <div class="output-text">
  4406. <div class="output-title">分享到社区</div>
  4407. <div class="output-desc">让好友看到你的搭配</div>
  4408. </div>
  4409. </button>
  4410. <button class="output-btn purchase" onclick="buyNow()">
  4411. <span class="output-icon">🛒</span>
  4412. <div class="output-text">
  4413. <div class="output-title">一键购买</div>
  4414. <div class="output-desc">立即下单同款服装</div>
  4415. </div>
  4416. </button>
  4417. </div>
  4418. </div>
  4419. <div class="fitting-actions">
  4420. <button class="fitting-btn back" onclick="previousStep('clothing')">重新选择</button>
  4421. <button class="fitting-btn retry" onclick="retryFitting()">重新试穿</button>
  4422. </div>
  4423. </div>
  4424. </div>
  4425. </main>
  4426. </div>
  4427. <!-- 社区页面 -->
  4428. <div id="community-page" class="page community-page">
  4429. <div class="community-header">
  4430. <div class="community-header-top">
  4431. <h1>设计社区</h1>
  4432. <!-- 新增:社区页面发布按钮 -->
  4433. <button class="publish-btn" onclick="openUploadModal()">
  4434. <span class="publish-icon">📝</span>
  4435. 发布作品
  4436. </button>
  4437. </div>
  4438. <p>与全球设计师交流创意</p>
  4439. <div class="community-stats">
  4440. <div class="stat-item">
  4441. <div class="stat-number">12.8k</div>
  4442. <div class="stat-label">活跃用户</div>
  4443. </div>
  4444. <div class="stat-item">
  4445. <div class="stat-number">3.2k</div>
  4446. <div class="stat-label">今日作品</div>
  4447. </div>
  4448. <div class="stat-item">
  4449. <div class="stat-number">156</div>
  4450. <div class="stat-label">在线设计师</div>
  4451. </div>
  4452. </div>
  4453. </div>
  4454. <main class="main-content">
  4455. <div style="margin: 20px;">
  4456. <!-- 热门话题 -->
  4457. <div style="background: white; border-radius: 15px; padding: 20px; margin-bottom: 20px; box-shadow: 0 5px 20px rgba(0,0,0,0.1);">
  4458. <h4 style="margin-bottom: 15px; font-size: 16px;">🔥 热门话题</h4>
  4459. <div style="display: flex; flex-wrap: wrap; gap: 8px;">
  4460. <span style="background: #ff6b6b; color: white; padding: 6px 12px; border-radius: 20px; font-size: 12px; cursor: pointer;">#春季时尚</span>
  4461. <span style="background: #4ecdc4; color: white; padding: 6px 12px; border-radius: 20px; font-size: 12px; cursor: pointer;">#环保设计</span>
  4462. <span style="background: #45b7d1; color: white; padding: 6px 12px; border-radius: 20px; font-size: 12px; cursor: pointer;">#极简主义</span>
  4463. <span style="background: #96ceb4; color: white; padding: 6px 12px; border-radius: 20px; font-size: 12px; cursor: pointer;">#复古回潮</span>
  4464. </div>
  4465. </div>
  4466. <!-- 设计师排行榜 -->
  4467. <div style="background: white; border-radius: 15px; padding: 20px; margin-bottom: 20px; box-shadow: 0 5px 20px rgba(0,0,0,0.1);">
  4468. <h4 style="margin-bottom: 15px; font-size: 16px;">🏆 本周设计师排行</h4>
  4469. <div style="display: flex; flex-direction: column; gap: 12px;">
  4470. <div style="display: flex; align-items: center; justify-content: space-between; padding: 10px; background: #f8f9fa; border-radius: 10px;">
  4471. <div style="display: flex; align-items: center; gap: 12px;">
  4472. <div style="width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(45deg, #ff6b6b, #ffa726); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold;">1</div>
  4473. <div>
  4474. <div style="font-weight: 600; font-size: 14px;">设计大师Alex</div>
  4475. <div style="font-size: 12px; color: #666;">点赞数: 8.9k</div>
  4476. </div>
  4477. </div>
  4478. <div style="font-size: 20px;">👑</div>
  4479. </div>
  4480. <div style="display: flex; align-items: center; justify-content: space-between; padding: 10px; background: #f8f9fa; border-radius: 10px;">
  4481. <div style="display: flex; align-items: center; gap: 12px;">
  4482. <div style="width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(45deg, #4ecdc4, #44a08d); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold;">2</div>
  4483. <div>
  4484. <div style="font-weight: 600; font-size: 14px;">时尚达人Lisa</div>
  4485. <div style="font-size: 12px; color: #666;">点赞数: 7.2k</div>
  4486. </div>
  4487. </div>
  4488. <div style="font-size: 20px;">🥈</div>
  4489. </div>
  4490. <div style="display: flex; align-items: center; justify-content: space-between; padding: 10px; background: #f8f9fa; border-radius: 10px;">
  4491. <div style="display: flex; align-items: center; gap: 12px;">
  4492. <div style="width: 40px; height: 40px; border-radius: 50%; background: linear-gradient(45deg, #667eea, #764ba2); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold;">3</div>
  4493. <div>
  4494. <div style="font-weight: 600; font-size: 14px;">创意师Mike</div>
  4495. <div style="font-size: 12px; color: #666;">点赞数: 5.8k</div>
  4496. </div>
  4497. </div>
  4498. <div style="font-size: 20px;">🥉</div>
  4499. </div>
  4500. </div>
  4501. </div>
  4502. <!-- 最新作品 -->
  4503. <div style="background: white; border-radius: 15px; padding: 20px; box-shadow: 0 5px 20px rgba(0,0,0,0.1);">
  4504. <h4 style="margin-bottom: 15px; font-size: 16px;">✨ 最新作品</h4>
  4505. <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px;">
  4506. <div style="background: linear-gradient(45deg, #a8edea 0%, #fed6e3 100%); border-radius: 12px; height: 120px; display: flex; align-items: center; justify-content: center; font-size: 36px; cursor: pointer; transition: all 0.3s ease;" onclick="likeWork(this)">🌸</div>
  4507. <div style="background: linear-gradient(45deg, #667eea 0%, #764ba2 100%); border-radius: 12px; height: 120px; display: flex; align-items: center; justify-content: center; font-size: 36px; cursor: pointer; transition: all 0.3s ease;" onclick="likeWork(this)">⚡</div>
  4508. </div>
  4509. </div>
  4510. </div>
  4511. </main>
  4512. </div>
  4513. <!-- 个人中心页面 -->
  4514. <div id="profile-page" class="page profile-page">
  4515. <div class="profile-header">
  4516. <div class="avatar">👤</div>
  4517. <h2>时尚设计师</h2>
  4518. <p>让创意成为生活的一部分</p>
  4519. </div>
  4520. <div class="profile-menu">
  4521. <div class="menu-item" onclick="showDrafts()">
  4522. <div class="menu-left">
  4523. <span class="menu-icon">🎨</span>
  4524. <span>我的设计稿</span>
  4525. </div>
  4526. <span>></span>
  4527. </div>
  4528. <div class="menu-item" onclick="showMyWorks()">
  4529. <div class="menu-left">
  4530. <span class="menu-icon">📋</span>
  4531. <span>我的作品</span>
  4532. </div>
  4533. <span>></span>
  4534. </div>
  4535. <div class="menu-item" onclick="showTryOnHistory()">
  4536. <div class="menu-left">
  4537. <span class="menu-icon">👕</span>
  4538. <span>试穿历史</span>
  4539. </div>
  4540. <span>></span>
  4541. </div>
  4542. <div class="menu-item" onclick="showOrders()">
  4543. <div class="menu-left">
  4544. <span class="menu-icon">📦</span>
  4545. <span>订单管理</span>
  4546. </div>
  4547. <span>></span>
  4548. </div>
  4549. <div class="menu-item" onclick="showCollections()">
  4550. <div class="menu-left">
  4551. <span class="menu-icon">❤️</span>
  4552. <span>收藏夹</span>
  4553. </div>
  4554. <span>></span>
  4555. </div>
  4556. <div class="menu-item" onclick="showFollowers()">
  4557. <div class="menu-left">
  4558. <span class="menu-icon">👥</span>
  4559. <span>粉丝管理</span>
  4560. </div>
  4561. <span>></span>
  4562. </div>
  4563. <div class="menu-item" onclick="showSettings()">
  4564. <div class="menu-left">
  4565. <span class="menu-icon">⚙️</span>
  4566. <span>设置</span>
  4567. </div>
  4568. <span>></span>
  4569. </div>
  4570. </div>
  4571. </div>
  4572. <!-- 底部导航 -->
  4573. <nav class="bottom-nav">
  4574. <div class="nav-item active" data-page="home">
  4575. <div class="nav-icon">🏠</div>
  4576. <div class="nav-text">首页</div>
  4577. </div>
  4578. <div class="nav-item" data-page="design">
  4579. <div class="nav-icon">🎨</div>
  4580. <div class="nav-text">设计</div>
  4581. </div>
  4582. <div class="nav-item" data-page="ar">
  4583. <div class="nav-icon">📱</div>
  4584. <div class="nav-text">试衣</div>
  4585. </div>
  4586. <div class="nav-item" data-page="community">
  4587. <div class="nav-icon">👥</div>
  4588. <div class="nav-text">社区</div>
  4589. </div>
  4590. <div class="nav-item" data-page="profile">
  4591. <div class="nav-icon">👤</div>
  4592. <div class="nav-text">我的</div>
  4593. </div>
  4594. </nav>
  4595. <!-- AI对话悬浮球 -->
  4596. <div id="aiFloatingBall" class="ai-floating-ball">
  4597. <div class="floating-ball-icon">🤖</div>
  4598. <div class="breathing-ring"></div>
  4599. </div>
  4600. <!-- AI全屏对话界面 -->
  4601. <div id="aiChatModal" class="ai-chat-modal" style="display: none;">
  4602. <div class="ai-chat-container">
  4603. <!-- 对话头部 -->
  4604. <div class="ai-chat-header">
  4605. <div class="ai-chat-avatar">
  4606. <span class="avatar-icon">🤖</span>
  4607. <div class="avatar-status"></div>
  4608. </div>
  4609. <div class="ai-chat-info">
  4610. <h3>AI时尚顾问 <span style="font-size: 12px; background: linear-gradient(45deg, #ff6b6b, #ffa726); padding: 2px 6px; border-radius: 8px; color: white;">DeepSeek驱动</span></h3>
  4611. <p id="aiChatSubtitle">智能搭配助手在线中...</p>
  4612. </div>
  4613. <button class="ai-chat-close" onclick="closeAIChat()">✕</button>
  4614. </div>
  4615. <!-- 对话消息区 -->
  4616. <div class="ai-chat-messages" id="aiChatMessages">
  4617. <div class="ai-message">
  4618. <div class="message-avatar">🤖</div>
  4619. <div class="message-content">
  4620. <div class="message-text ai-formatted">
  4621. **你好!我是由DeepSeek AI驱动的专属时尚顾问** ✨<br><br>
  4622. 我可以帮您:<br>
  4623. • **服装搭配** - 根据场合推荐最佳组合<br>
  4624. • **配色建议** - 打造和谐视觉效果<br>
  4625. • **风格分析** - 找到最适合您的穿衣风格<br><br>
  4626. > 💡 想聊什么时尚话题呢?我会为您提供专业的建议!
  4627. </div>
  4628. <div class="message-time">刚刚</div>
  4629. </div>
  4630. </div>
  4631. </div>
  4632. <!-- 快捷指令 -->
  4633. <div class="ai-quick-commands" id="aiQuickCommands">
  4634. <div class="quick-command" onclick="sendQuickCommand('帮我搭配一套商务装')">
  4635. <span class="command-icon">👔</span>
  4636. <span>商务装搭配</span>
  4637. </div>
  4638. <div class="quick-command" onclick="sendQuickCommand('推荐春季流行色')">
  4639. <span class="command-icon">🌸</span>
  4640. <span>春季流行色</span>
  4641. </div>
  4642. <div class="quick-command" onclick="sendQuickCommand('分析我的穿衣风格')">
  4643. <span class="command-icon">✨</span>
  4644. <span>风格分析</span>
  4645. </div>
  4646. <div class="quick-command" onclick="sendQuickCommand('约会穿什么好看')">
  4647. <span class="command-icon">💕</span>
  4648. <span>约会搭配</span>
  4649. </div>
  4650. </div>
  4651. <!-- 输入工具栏 -->
  4652. <div class="ai-chat-input-area">
  4653. <div class="input-toolbar">
  4654. <button class="input-tool" onclick="startVoiceInput()" title="语音输入">
  4655. <span class="tool-icon">🎤</span>
  4656. </button>
  4657. <button class="input-tool" onclick="uploadImage()" title="图片识别">
  4658. <span class="tool-icon">📷</span>
  4659. </button>
  4660. <button class="input-tool" onclick="showEmoji()" title="表情">
  4661. <span class="tool-icon">😊</span>
  4662. </button>
  4663. </div>
  4664. <div class="input-container">
  4665. <input
  4666. type="text"
  4667. id="aiChatInput"
  4668. placeholder="说说你的搭配需求..."
  4669. onkeypress="handleChatInputKeypress(event)"
  4670. >
  4671. <button class="send-button" onclick="sendMessage()">
  4672. <span class="send-icon">➤</span>
  4673. </button>
  4674. </div>
  4675. </div>
  4676. </div>
  4677. </div>
  4678. <!-- AI推荐结果页面 -->
  4679. <div id="aiRecommendationModal" class="ai-recommendation-modal" style="display: none;">
  4680. <div class="recommendation-container">
  4681. <div class="recommendation-header">
  4682. <h2>🎯 专属推荐方案</h2>
  4683. <button class="close-recommendation" onclick="closeRecommendation()">✕</button>
  4684. </div>
  4685. <div class="recommendation-content">
  4686. <!-- 3D穿搭展示 -->
  4687. <div class="recommendation-3d-section">
  4688. <div class="recommendation-3d-viewer">
  4689. <div class="model-3d-container">
  4690. <div class="model-3d-display">👤</div>
  4691. <div class="model-controls">
  4692. <button class="model-control" onclick="rotateModel('left')">↶</button>
  4693. <button class="model-control" onclick="rotateModel('right')">↷</button>
  4694. <button class="model-control" onclick="resetModel()">⌂</button>
  4695. </div>
  4696. </div>
  4697. </div>
  4698. <!-- 方案选择器 -->
  4699. <div class="scheme-selector">
  4700. <h4>推荐方案</h4>
  4701. <div class="scheme-tabs">
  4702. <div class="scheme-tab active" onclick="selectScheme('scheme1')">方案1</div>
  4703. <div class="scheme-tab" onclick="selectScheme('scheme2')">方案2</div>
  4704. <div class="scheme-tab" onclick="selectScheme('scheme3')">方案3</div>
  4705. </div>
  4706. </div>
  4707. </div>
  4708. <!-- 配色原理说明 -->
  4709. <div class="color-theory-section">
  4710. <h4>🎨 配色原理解析</h4>
  4711. <div class="theory-content" id="colorTheoryContent">
  4712. <div class="theory-card">
  4713. <div class="theory-icon">🎯</div>
  4714. <div class="theory-text">
  4715. <h5>主色调选择</h5>
  4716. <p>基于您的肤色和喜好,选择了温暖的蓝色作为主色调,既显稳重又不失活力。</p>
  4717. </div>
  4718. </div>
  4719. <div class="theory-card">
  4720. <div class="theory-icon">🌈</div>
  4721. <div class="theory-text">
  4722. <h5>色彩搭配</h5>
  4723. <p>采用邻近色搭配法,蓝色与紫色的组合营造出和谐优雅的视觉效果。</p>
  4724. </div>
  4725. </div>
  4726. <div class="theory-card">
  4727. <div class="theory-icon">✨</div>
  4728. <div class="theory-text">
  4729. <h5>层次感营造</h5>
  4730. <p>通过深浅不同的蓝色系形成层次,增加整体造型的丰富度和立体感。</p>
  4731. </div>
  4732. </div>
  4733. </div>
  4734. </div>
  4735. <!-- 操作按钮 -->
  4736. <div class="recommendation-actions">
  4737. <button class="action-btn secondary" onclick="shareRecommendation()">
  4738. <span class="btn-icon">📤</span>
  4739. <span>分享方案</span>
  4740. </button>
  4741. <button class="action-btn secondary" onclick="saveRecommendation()">
  4742. <span class="btn-icon">💾</span>
  4743. <span>收藏方案</span>
  4744. </button>
  4745. <button class="action-btn primary" onclick="importToDesignCenter()">
  4746. <span class="btn-icon">🎨</span>
  4747. <span>导入设计中心</span>
  4748. </button>
  4749. </div>
  4750. </div>
  4751. </div>
  4752. </div>
  4753. <!-- 模态框 -->
  4754. <div id="modal" class="modal">
  4755. <div class="modal-content">
  4756. <h3 id="modalTitle">开始设计</h3>
  4757. <p id="modalText">选择你想要设计的服装类型</p>
  4758. <div class="modal-actions">
  4759. <button class="btn btn-secondary" onclick="closeModal()">取消</button>
  4760. <button class="btn btn-primary" onclick="startDesign()">开始</button>
  4761. </div>
  4762. </div>
  4763. </div>
  4764. <!-- 设置模态框 -->
  4765. <div id="settingsModal" class="settings-modal">
  4766. <div class="settings-modal-content">
  4767. <div class="settings-header">
  4768. <h2>设置</h2>
  4769. <button class="close-btn" onclick="closeSettingsModal()">×</button>
  4770. </div>
  4771. <div class="settings-body">
  4772. <!-- 个人资料部分 -->
  4773. <div class="settings-section">
  4774. <h3>个人资料</h3>
  4775. <div class="profile-info">
  4776. <div class="profile-avatar">
  4777. <div class="avatar-circle" onclick="changeAvatar()">
  4778. <img id="userAvatar" src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'><circle cx='30' cy='30' r='30' fill='%23ff6b6b'/><circle cx='30' cy='22' r='8' fill='white'/><ellipse cx='30' cy='45' rx='15' ry='10' fill='white'/></svg>" alt="头像">
  4779. <div class="avatar-edit">📷</div>
  4780. </div>
  4781. </div>
  4782. <div class="profile-details">
  4783. <div class="form-group">
  4784. <label for="userName">用户名</label>
  4785. <input type="text" id="userName" value="时尚设计师" placeholder="输入您的用户名">
  4786. </div>
  4787. <div class="form-group">
  4788. <label for="userBio">个人简介</label>
  4789. <textarea id="userBio" placeholder="介绍一下您自己...">热爱时尚设计,专注于创新与美学的完美结合</textarea>
  4790. </div>
  4791. <div class="form-group">
  4792. <label for="userLocation">所在地</label>
  4793. <input type="text" id="userLocation" value="上海" placeholder="您的所在城市">
  4794. </div>
  4795. </div>
  4796. </div>
  4797. </div>
  4798. <!-- 账户安全 -->
  4799. <div class="settings-section">
  4800. <h3>账户安全</h3>
  4801. <div class="security-items">
  4802. <div class="security-item" onclick="changePassword()">
  4803. <div class="security-left">
  4804. <span class="security-icon">🔒</span>
  4805. <div>
  4806. <div class="security-title">修改密码</div>
  4807. <div class="security-desc">定期更新密码保护账户安全</div>
  4808. </div>
  4809. </div>
  4810. <span class="arrow">></span>
  4811. </div>
  4812. <div class="security-item" onclick="bindPhone()">
  4813. <div class="security-left">
  4814. <span class="security-icon">📱</span>
  4815. <div>
  4816. <div class="security-title">手机号绑定</div>
  4817. <div class="security-desc">已绑定:138****8888</div>
  4818. </div>
  4819. </div>
  4820. <span class="arrow">></span>
  4821. </div>
  4822. <div class="security-item" onclick="bindEmail()">
  4823. <div class="security-left">
  4824. <span class="security-icon">📧</span>
  4825. <div>
  4826. <div class="security-title">邮箱绑定</div>
  4827. <div class="security-desc">user@example.com</div>
  4828. </div>
  4829. </div>
  4830. <span class="arrow">></span>
  4831. </div>
  4832. </div>
  4833. </div>
  4834. <!-- 隐私设置 -->
  4835. <div class="settings-section">
  4836. <h3>隐私设置</h3>
  4837. <div class="privacy-items">
  4838. <div class="privacy-item">
  4839. <div class="privacy-left">
  4840. <span class="privacy-icon">👁️</span>
  4841. <div>
  4842. <div class="privacy-title">作品可见性</div>
  4843. <div class="privacy-desc">设置谁可以查看您的作品</div>
  4844. </div>
  4845. </div>
  4846. <select class="privacy-select">
  4847. <option value="public">公开</option>
  4848. <option value="followers">仅粉丝</option>
  4849. <option value="private">私人</option>
  4850. </select>
  4851. </div>
  4852. <div class="privacy-item">
  4853. <div class="privacy-left">
  4854. <span class="privacy-icon">🔔</span>
  4855. <div>
  4856. <div class="privacy-title">消息通知</div>
  4857. <div class="privacy-desc">接收点赞、评论等通知</div>
  4858. </div>
  4859. </div>
  4860. <label class="switch">
  4861. <input type="checkbox" checked>
  4862. <span class="slider"></span>
  4863. </label>
  4864. </div>
  4865. <div class="privacy-item">
  4866. <div class="privacy-left">
  4867. <span class="privacy-icon">📊</span>
  4868. <div>
  4869. <div class="privacy-title">数据分析</div>
  4870. <div class="privacy-desc">允许匿名数据分析</div>
  4871. </div>
  4872. </div>
  4873. <label class="switch">
  4874. <input type="checkbox" checked>
  4875. <span class="slider"></span>
  4876. </label>
  4877. </div>
  4878. </div>
  4879. </div>
  4880. <!-- 应用设置 -->
  4881. <div class="settings-section">
  4882. <h3>应用设置</h3>
  4883. <div class="app-items">
  4884. <div class="app-item" onclick="showAbout()">
  4885. <div class="app-left">
  4886. <span class="app-icon">ℹ️</span>
  4887. <span class="app-title">关于应用</span>
  4888. </div>
  4889. <div class="app-right">
  4890. <span class="version">v1.0.0</span>
  4891. <span class="arrow">></span>
  4892. </div>
  4893. </div>
  4894. <div class="app-item" onclick="clearCache()">
  4895. <div class="app-left">
  4896. <span class="app-icon">🗑️</span>
  4897. <span class="app-title">清除缓存</span>
  4898. </div>
  4899. <div class="app-right">
  4900. <span class="cache-size">23.5MB</span>
  4901. <span class="arrow">></span>
  4902. </div>
  4903. </div>
  4904. <div class="app-item" onclick="feedback()">
  4905. <div class="app-left">
  4906. <span class="app-icon">💬</span>
  4907. <span class="app-title">意见反馈</span>
  4908. </div>
  4909. <span class="arrow">></span>
  4910. </div>
  4911. </div>
  4912. </div>
  4913. </div>
  4914. <div class="settings-footer">
  4915. <button class="save-btn" onclick="saveSettings()">保存设置</button>
  4916. <button class="logout-btn" onclick="confirmLogout()">退出登录</button>
  4917. </div>
  4918. </div>
  4919. </div>
  4920. <!-- 上传作品模态框 -->
  4921. <div id="uploadModal" class="upload-modal">
  4922. <div class="upload-modal-content">
  4923. <!-- 步骤指示器 -->
  4924. <div class="upload-steps">
  4925. <div class="step active">
  4926. <div class="step-number">1</div>
  4927. <div class="step-label">选择类型</div>
  4928. </div>
  4929. <div class="step">
  4930. <div class="step-number">2</div>
  4931. <div class="step-label">上传内容</div>
  4932. </div>
  4933. <div class="step">
  4934. <div class="step-number">3</div>
  4935. <div class="step-label">作品信息</div>
  4936. </div>
  4937. <div class="step">
  4938. <div class="step-number">4</div>
  4939. <div class="step-label">发布设置</div>
  4940. </div>
  4941. </div>
  4942. <!-- 步骤1: 选择作品类型 -->
  4943. <div class="upload-step active">
  4944. <h3>选择作品类型</h3>
  4945. <div class="work-types">
  4946. <div class="work-type" data-type="design" onclick="selectWorkType('design')">
  4947. <div class="type-icon">🎨</div>
  4948. <div class="type-name">设计稿</div>
  4949. <div class="type-desc">分享你的原创设计图稿</div>
  4950. </div>
  4951. <div class="work-type" data-type="photo" onclick="selectWorkType('photo')">
  4952. <div class="type-icon">📸</div>
  4953. <div class="type-name">实物照片</div>
  4954. <div class="type-desc">展示制作完成的服装作品</div>
  4955. </div>
  4956. <div class="work-type" data-type="video" onclick="selectWorkType('video')">
  4957. <div class="type-icon">🎬</div>
  4958. <div class="type-name">视频展示</div>
  4959. <div class="type-desc">动态展示服装效果</div>
  4960. </div>
  4961. <div class="work-type" data-type="3d" onclick="selectWorkType('3d')">
  4962. <div class="type-icon">🎭</div>
  4963. <div class="type-name">3D模型</div>
  4964. <div class="type-desc">上传3D服装模型文件</div>
  4965. </div>
  4966. </div>
  4967. </div>
  4968. <!-- 步骤2: 上传内容 -->
  4969. <div class="upload-step">
  4970. <h3>上传内容</h3>
  4971. <div class="upload-options">
  4972. <!-- 文件上传区域 -->
  4973. <div class="upload-section">
  4974. <h4>📁 上传文件</h4>
  4975. <div class="file-upload-area" onclick="triggerFileUpload()">
  4976. <div class="upload-placeholder">
  4977. <div class="upload-icon">📤</div>
  4978. <div class="upload-text">点击上传文件</div>
  4979. <div class="upload-hint">支持图片、视频格式,最多9个文件</div>
  4980. </div>
  4981. </div>
  4982. <input type="file" id="fileInput" multiple accept="image/*,video/*" style="display: none;" onchange="handleFileUpload(event)">
  4983. <div id="uploadPreview" class="upload-preview"></div>
  4984. </div>
  4985. <!-- 3D文件上传 -->
  4986. <div class="upload-section" id="3dUploadSection" style="display: none;">
  4987. <h4>🎭 上传3D模型</h4>
  4988. <div class="file-upload-area" onclick="trigger3DUpload()">
  4989. <div class="upload-placeholder">
  4990. <div class="upload-icon">🎯</div>
  4991. <div class="upload-text">上传3D模型文件</div>
  4992. <div class="upload-hint">支持 .obj, .fbx, .gltf 格式</div>
  4993. </div>
  4994. </div>
  4995. <input type="file" id="file3DInput" accept=".obj,.fbx,.gltf" style="display: none;" onchange="handle3DUpload(event)">
  4996. </div>
  4997. <!-- 从我的设计选择 -->
  4998. <div class="upload-section">
  4999. <h4>🎨 从我的设计选择</h4>
  5000. <div class="my-designs-grid">
  5001. <div class="design-item" onclick="selectFromMyDesigns(1)">
  5002. <div class="design-preview">👕</div>
  5003. <div class="design-name">春季T恤</div>
  5004. </div>
  5005. <div class="design-item" onclick="selectFromMyDesigns(2)">
  5006. <div class="design-preview">👗</div>
  5007. <div class="design-name">夏日连衣裙</div>
  5008. </div>
  5009. <div class="design-item" onclick="selectFromMyDesigns(3)">
  5010. <div class="design-preview">🧥</div>
  5011. <div class="design-name">秋季外套</div>
  5012. </div>
  5013. <div class="design-item" onclick="selectFromMyDesigns(4)">
  5014. <div class="design-preview">👖</div>
  5015. <div class="design-name">休闲裤</div>
  5016. </div>
  5017. <div class="design-item" onclick="selectFromMyDesigns(5)">
  5018. <div class="design-preview">🧣</div>
  5019. <div class="design-name">围巾设计</div>
  5020. </div>
  5021. <div class="design-item" onclick="selectFromMyDesigns(6)">
  5022. <div class="design-preview">👒</div>
  5023. <div class="design-name">帽子系列</div>
  5024. </div>
  5025. </div>
  5026. </div>
  5027. </div>
  5028. </div>
  5029. <!-- 步骤3: 作品信息 -->
  5030. <div class="upload-step">
  5031. <h3>作品信息</h3>
  5032. <div class="description-form">
  5033. <div class="form-group">
  5034. <label for="workTitle">作品标题 *</label>
  5035. <input type="text" id="workTitle" placeholder="给你的作品起个好听的名字" maxlength="50">
  5036. <div class="char-count"><span id="titleCount">0</span>/50</div>
  5037. </div>
  5038. <div class="form-group">
  5039. <label for="workDescription">作品描述</label>
  5040. <textarea id="workDescription" placeholder="介绍一下你的设计理念和创作过程..." maxlength="500"></textarea>
  5041. <div class="char-count"><span id="descCount">0</span>/500</div>
  5042. </div>
  5043. <div class="form-group">
  5044. <label>选择分类</label>
  5045. <select>
  5046. <option value="">请选择分类</option>
  5047. <option value="casual">休闲装</option>
  5048. <option value="formal">正装</option>
  5049. <option value="sport">运动装</option>
  5050. <option value="evening">晚装</option>
  5051. <option value="accessories">配饰</option>
  5052. </select>
  5053. </div>
  5054. <div class="tags-container">
  5055. <label>添加标签</label>
  5056. <div class="popular-tags">
  5057. <span class="tag" onclick="toggleTag(this)">#时尚</span>
  5058. <span class="tag" onclick="toggleTag(this)">#原创</span>
  5059. <span class="tag" onclick="toggleTag(this)">#简约</span>
  5060. <span class="tag" onclick="toggleTag(this)">#复古</span>
  5061. <span class="tag" onclick="toggleTag(this)">#街头</span>
  5062. <span class="tag" onclick="toggleTag(this)">#优雅</span>
  5063. <span class="tag" onclick="toggleTag(this)">#运动</span>
  5064. <span class="tag" onclick="toggleTag(this)">#环保</span>
  5065. </div>
  5066. <input type="text" id="customTag" placeholder="输入自定义标签后按回车" onkeypress="addCustomTag(event)">
  5067. </div>
  5068. </div>
  5069. </div>
  5070. <!-- 步骤4: 发布设置 -->
  5071. <div class="upload-step">
  5072. <h3>发布设置</h3>
  5073. <div class="publish-settings">
  5074. <div class="setting-group">
  5075. <label>作品可见性</label>
  5076. <div class="radio-group">
  5077. <label class="radio-option">
  5078. <input type="radio" name="visibility" value="public" checked>
  5079. <div class="radio-custom"></div>
  5080. <div class="option-content">
  5081. <div class="option-title">公开</div>
  5082. <div class="option-desc">所有人都可以查看你的作品</div>
  5083. </div>
  5084. </label>
  5085. <label class="radio-option">
  5086. <input type="radio" name="visibility" value="followers">
  5087. <div class="radio-custom"></div>
  5088. <div class="option-content">
  5089. <div class="option-title">仅粉丝可见</div>
  5090. <div class="option-desc">只有关注你的用户可以查看</div>
  5091. </div>
  5092. </label>
  5093. <label class="radio-option">
  5094. <input type="radio" name="visibility" value="private">
  5095. <div class="radio-custom"></div>
  5096. <div class="option-content">
  5097. <div class="option-title">私密</div>
  5098. <div class="option-desc">只有你自己可以查看</div>
  5099. </div>
  5100. </label>
  5101. </div>
  5102. </div>
  5103. <div class="setting-group">
  5104. <label>下载权限</label>
  5105. <div class="radio-group">
  5106. <label class="radio-option">
  5107. <input type="radio" name="download" value="allow" checked>
  5108. <div class="radio-custom"></div>
  5109. <div class="option-content">
  5110. <div class="option-title">允许下载</div>
  5111. <div class="option-desc">其他用户可以下载你的作品</div>
  5112. </div>
  5113. </label>
  5114. <label class="radio-option">
  5115. <input type="radio" name="download" value="forbid">
  5116. <div class="radio-custom"></div>
  5117. <div class="option-content">
  5118. <div class="option-title">禁止下载</div>
  5119. <div class="option-desc">保护你的原创作品</div>
  5120. </div>
  5121. </label>
  5122. </div>
  5123. </div>
  5124. <div class="setting-group">
  5125. <label>其他设置</label>
  5126. <label class="checkbox-option">
  5127. <input type="checkbox" id="allowComments" checked>
  5128. <div class="checkbox-custom"></div>
  5129. <div class="option-content">
  5130. <div class="option-title">允许评论</div>
  5131. <div class="option-desc">其他用户可以对你的作品进行评论</div>
  5132. </div>
  5133. </label>
  5134. <label class="checkbox-option">
  5135. <input type="checkbox" id="copyrightAgree">
  5136. <div class="checkbox-custom"></div>
  5137. <div class="option-content">
  5138. <div class="option-title">版权声明 *</div>
  5139. <div class="option-desc">我确认拥有此作品的版权,并同意平台使用条款</div>
  5140. </div>
  5141. </label>
  5142. </div>
  5143. </div>
  5144. </div>
  5145. <!-- 模态框底部按钮 -->
  5146. <div class="upload-modal-footer">
  5147. <button class="btn btn-outline" onclick="closeUploadModal()">取消</button>
  5148. <button class="btn btn-outline" id="prevBtn" onclick="prevStep()" style="display: none;">上一步</button>
  5149. <button class="btn btn-primary" id="nextBtn" onclick="nextUploadStep()">下一步</button>
  5150. <button class="btn btn-primary" id="publishBtn" onclick="publishWork()" style="display: none;">发布作品</button>
  5151. </div>
  5152. </div>
  5153. </div>
  5154. <!-- 草稿箱模态框 -->
  5155. <div id="draftsModal" class="upload-modal">
  5156. <div class="upload-modal-content drafts-content">
  5157. <div style="padding: 20px 30px; border-bottom: 1px solid #e9ecef;">
  5158. <h3>草稿箱</h3>
  5159. <p style="color: #666; font-size: 14px; margin-top: 5px;">管理你的草稿作品</p>
  5160. </div>
  5161. <div class="drafts-list">
  5162. <div class="draft-item">
  5163. <div class="draft-preview">👕</div>
  5164. <div class="draft-info">
  5165. <div class="draft-title">春季T恤设计</div>
  5166. <div class="draft-time">保存于 2024-03-15</div>
  5167. </div>
  5168. <div class="draft-actions">
  5169. <button onclick="editDraft(1)">编辑</button>
  5170. <button onclick="deleteDraft(1)">删除</button>
  5171. </div>
  5172. </div>
  5173. <div class="draft-item">
  5174. <div class="draft-preview">👗</div>
  5175. <div class="draft-info">
  5176. <div class="draft-title">夏日连衣裙</div>
  5177. <div class="draft-time">保存于 2024-03-14</div>
  5178. </div>
  5179. <div class="draft-actions">
  5180. <button onclick="editDraft(2)">编辑</button>
  5181. <button onclick="deleteDraft(2)">删除</button>
  5182. </div>
  5183. </div>
  5184. <div class="draft-item">
  5185. <div class="draft-preview">🧥</div>
  5186. <div class="draft-info">
  5187. <div class="draft-title">秋季外套概念</div>
  5188. <div class="draft-time">保存于 2024-03-12</div>
  5189. </div>
  5190. <div class="draft-actions">
  5191. <button onclick="editDraft(3)">编辑</button>
  5192. <button onclick="deleteDraft(3)">删除</button>
  5193. </div>
  5194. </div>
  5195. </div>
  5196. <div class="upload-modal-footer">
  5197. <button class="btn btn-outline" onclick="closeDraftsModal()">关闭</button>
  5198. <button class="btn btn-primary" onclick="openUploadModal(); closeDraftsModal();">新建作品</button>
  5199. </div>
  5200. </div>
  5201. </div>
  5202. <!-- 我的作品模态框 -->
  5203. <div id="myWorksModal" class="upload-modal">
  5204. <div class="upload-modal-content">
  5205. <div style="padding: 20px 30px; border-bottom: 1px solid #e9ecef;">
  5206. <h3>我的作品</h3>
  5207. <p style="color: #666; font-size: 14px; margin-top: 5px;">管理你发布的作品</p>
  5208. </div>
  5209. <!-- 标签页 -->
  5210. <div class="works-tabs">
  5211. <div class="tab active" onclick="switchWorksTab('published')">已发布</div>
  5212. <div class="tab" onclick="switchWorksTab('analytics')">数据分析</div>
  5213. </div>
  5214. <!-- 已发布作品 -->
  5215. <div id="publishedWorks" class="works-content">
  5216. <div class="work-item">
  5217. <div class="work-preview">🌸</div>
  5218. <div class="work-info">
  5219. <div class="work-title">春季花朵印花T恤</div>
  5220. <div class="work-stats">
  5221. <span>❤️ 1.2k</span>
  5222. <span>💬 89</span>
  5223. <span>👁️ 5.6k</span>
  5224. </div>
  5225. </div>
  5226. <div class="work-actions">
  5227. <button onclick="editWork(1)">编辑</button>
  5228. <button onclick="deleteWork(1)">删除</button>
  5229. </div>
  5230. </div>
  5231. <div class="work-item">
  5232. <div class="work-preview">⚡</div>
  5233. <div class="work-info">
  5234. <div class="work-title">未来科技风外套</div>
  5235. <div class="work-stats">
  5236. <span>❤️ 2.1k</span>
  5237. <span>💬 156</span>
  5238. <span>👁️ 8.9k</span>
  5239. </div>
  5240. </div>
  5241. <div class="work-actions">
  5242. <button onclick="editWork(2)">编辑</button>
  5243. <button onclick="deleteWork(2)">删除</button>
  5244. </div>
  5245. </div>
  5246. <div class="work-item">
  5247. <div class="work-preview">🌿</div>
  5248. <div class="work-info">
  5249. <div class="work-title">环保材质连衣裙</div>
  5250. <div class="work-stats">
  5251. <span>❤️ 856</span>
  5252. <span>💬 67</span>
  5253. <span>👁️ 3.2k</span>
  5254. </div>
  5255. </div>
  5256. <div class="work-actions">
  5257. <button onclick="editWork(3)">编辑</button>
  5258. <button onclick="deleteWork(3)">删除</button>
  5259. </div>
  5260. </div>
  5261. </div>
  5262. <!-- 数据分析 -->
  5263. <div id="analyticsWorks" class="works-content" style="display: none;">
  5264. <div class="analytics-summary">
  5265. <div class="analytics-item">
  5266. <div class="analytics-number">12</div>
  5267. <div class="analytics-label">总作品数</div>
  5268. </div>
  5269. <div class="analytics-item">
  5270. <div class="analytics-number">8.9k</div>
  5271. <div class="analytics-label">总点赞数</div>
  5272. </div>
  5273. <div class="analytics-item">
  5274. <div class="analytics-number">2.3k</div>
  5275. <div class="analytics-label">总浏览量</div>
  5276. </div>
  5277. </div>
  5278. <div style="padding: 20px; text-align: center; color: #666;">
  5279. <div style="font-size: 48px; margin-bottom: 15px;">📊</div>
  5280. <div>详细数据分析功能</div>
  5281. <div style="font-size: 14px; margin-top: 8px;">即将上线,敬请期待</div>
  5282. </div>
  5283. </div>
  5284. <div class="upload-modal-footer">
  5285. <button class="btn btn-outline" onclick="closeMyWorksModal()">关闭</button>
  5286. <button class="btn btn-outline" onclick="showDrafts(); closeMyWorksModal();">草稿箱</button>
  5287. <button class="btn btn-primary" onclick="openUploadModal(); closeMyWorksModal();">发布新作品</button>
  5288. </div>
  5289. </div>
  5290. </div>
  5291. </div>
  5292. <script>
  5293. // =========================== API 服务层 ===========================
  5294. // API 配置
  5295. const API_CONFIG = {
  5296. baseURL: 'https://ghiuoimfghor.sealoshzh.site',
  5297. timeout: 10000,
  5298. retryCount: 3,
  5299. retryDelay: 1000
  5300. };
  5301. // 认证状态管理
  5302. class AuthManager {
  5303. constructor() {
  5304. this.token = localStorage.getItem('fashioncraft_token');
  5305. this.user = JSON.parse(localStorage.getItem('fashioncraft_user') || 'null');
  5306. this.refreshToken = localStorage.getItem('fashioncraft_refresh_token');
  5307. }
  5308. setAuth(data) {
  5309. this.token = data.token;
  5310. this.user = data.user_info || data;
  5311. if (data.refresh_token) {
  5312. this.refreshToken = data.refresh_token;
  5313. localStorage.setItem('fashioncraft_refresh_token', data.refresh_token);
  5314. }
  5315. localStorage.setItem('fashioncraft_token', this.token);
  5316. localStorage.setItem('fashioncraft_user', JSON.stringify(this.user));
  5317. }
  5318. clearAuth() {
  5319. this.token = null;
  5320. this.user = null;
  5321. this.refreshToken = null;
  5322. localStorage.removeItem('fashioncraft_token');
  5323. localStorage.removeItem('fashioncraft_user');
  5324. localStorage.removeItem('fashioncraft_refresh_token');
  5325. }
  5326. isAuthenticated() {
  5327. return !!this.token;
  5328. }
  5329. getAuthHeaders() {
  5330. return this.token ? { 'Authorization': `Bearer ${this.token}` } : {};
  5331. }
  5332. async refreshAuthToken() {
  5333. if (!this.refreshToken) {
  5334. throw new Error('No refresh token available');
  5335. }
  5336. try {
  5337. const response = await fetch(`${API_CONFIG.baseURL}/api/auth/refresh-token`, {
  5338. method: 'POST',
  5339. headers: {
  5340. 'Content-Type': 'application/json'
  5341. },
  5342. body: JSON.stringify({ refresh_token: this.refreshToken })
  5343. });
  5344. const data = await response.json();
  5345. if (data.code === 200) {
  5346. this.setAuth({ token: data.data.token, user_info: this.user });
  5347. return data.data.token;
  5348. } else {
  5349. throw new Error(data.message);
  5350. }
  5351. } catch (error) {
  5352. this.clearAuth();
  5353. throw error;
  5354. }
  5355. }
  5356. }
  5357. // 创建认证管理实例
  5358. const authManager = new AuthManager();
  5359. // HTTP 请求工具类
  5360. class ApiClient {
  5361. constructor() {
  5362. this.requestQueue = new Map();
  5363. }
  5364. async request(url, options = {}) {
  5365. const config = {
  5366. method: 'GET',
  5367. headers: {
  5368. 'Content-Type': 'application/json',
  5369. ...authManager.getAuthHeaders(),
  5370. ...options.headers
  5371. },
  5372. timeout: API_CONFIG.timeout,
  5373. ...options
  5374. };
  5375. // 添加重试机制
  5376. for (let i = 0; i < API_CONFIG.retryCount; i++) {
  5377. try {
  5378. const response = await this.fetchWithTimeout(`${API_CONFIG.baseURL}${url}`, config);
  5379. // 处理401错误 - Token过期
  5380. if (response.status === 401 && authManager.isAuthenticated()) {
  5381. try {
  5382. await authManager.refreshAuthToken();
  5383. // 更新请求头并重试
  5384. config.headers = {
  5385. ...config.headers,
  5386. ...authManager.getAuthHeaders()
  5387. };
  5388. return await this.fetchWithTimeout(`${API_CONFIG.baseURL}${url}`, config);
  5389. } catch (refreshError) {
  5390. // 刷新失败,跳转到登录
  5391. this.handleAuthError();
  5392. throw new Error('认证失败,请重新登录');
  5393. }
  5394. }
  5395. const data = await response.json();
  5396. if (data.code && data.code !== 200) {
  5397. throw new Error(data.message || '请求失败');
  5398. }
  5399. return data;
  5400. } catch (error) {
  5401. if (i === API_CONFIG.retryCount - 1) {
  5402. throw error;
  5403. }
  5404. await new Promise(resolve => setTimeout(resolve, API_CONFIG.retryDelay));
  5405. }
  5406. }
  5407. }
  5408. async fetchWithTimeout(url, config) {
  5409. const controller = new AbortController();
  5410. const timeout = setTimeout(() => controller.abort(), config.timeout);
  5411. try {
  5412. const response = await fetch(url, {
  5413. ...config,
  5414. signal: controller.signal
  5415. });
  5416. clearTimeout(timeout);
  5417. return response;
  5418. } catch (error) {
  5419. clearTimeout(timeout);
  5420. throw error;
  5421. }
  5422. }
  5423. handleAuthError() {
  5424. authManager.clearAuth();
  5425. showNotification('认证失效', '请重新登录');
  5426. // 可以在这里添加跳转到登录页面的逻辑
  5427. }
  5428. }
  5429. // 创建API客户端实例
  5430. const apiClient = new ApiClient();
  5431. // =========================== API 接口定义 ===========================
  5432. // 系统接口
  5433. const SystemAPI = {
  5434. // 健康检查
  5435. async checkHealth() {
  5436. return await apiClient.request('/health');
  5437. },
  5438. // 获取系统配置
  5439. async getConfig() {
  5440. return await apiClient.request('/api/system/config');
  5441. }
  5442. };
  5443. // 用户认证接口
  5444. const AuthAPI = {
  5445. // 用户注册
  5446. async register(userData) {
  5447. return await apiClient.request('/api/auth/register', {
  5448. method: 'POST',
  5449. body: JSON.stringify(userData)
  5450. });
  5451. },
  5452. // 用户登录
  5453. async login(credentials) {
  5454. return await apiClient.request('/api/auth/login', {
  5455. method: 'POST',
  5456. body: JSON.stringify(credentials)
  5457. });
  5458. },
  5459. // 用户登出
  5460. async logout() {
  5461. return await apiClient.request('/api/auth/logout', {
  5462. method: 'POST'
  5463. });
  5464. },
  5465. // 刷新令牌
  5466. async refreshToken(refreshToken) {
  5467. return await apiClient.request('/api/auth/refresh-token', {
  5468. method: 'POST',
  5469. body: JSON.stringify({ refresh_token: refreshToken })
  5470. });
  5471. }
  5472. };
  5473. // 用户信息管理接口
  5474. const UserAPI = {
  5475. // 获取用户个人信息
  5476. async getProfile() {
  5477. return await apiClient.request('/api/user/profile');
  5478. },
  5479. // 更新用户个人信息
  5480. async updateProfile(profileData) {
  5481. return await apiClient.request('/api/user/profile', {
  5482. method: 'PUT',
  5483. body: JSON.stringify(profileData)
  5484. });
  5485. },
  5486. // 修改密码
  5487. async changePassword(passwordData) {
  5488. return await apiClient.request('/api/user/change-password', {
  5489. method: 'POST',
  5490. body: JSON.stringify(passwordData)
  5491. });
  5492. }
  5493. };
  5494. // 设计模块接口
  5495. const DesignAPI = {
  5496. // 创建设计项目
  5497. async createDesign(designData) {
  5498. return await apiClient.request('/api/design/create', {
  5499. method: 'POST',
  5500. body: JSON.stringify(designData)
  5501. });
  5502. },
  5503. // 获取设计列表
  5504. async getDesignList(params = {}) {
  5505. const queryString = new URLSearchParams(params).toString();
  5506. return await apiClient.request(`/api/design/list?${queryString}`);
  5507. },
  5508. // 获取设计详情
  5509. async getDesignDetail(designId) {
  5510. return await apiClient.request(`/api/design/${designId}`);
  5511. },
  5512. // 更新设计
  5513. async updateDesign(designId, designData) {
  5514. return await apiClient.request(`/api/design/${designId}`, {
  5515. method: 'PUT',
  5516. body: JSON.stringify(designData)
  5517. });
  5518. },
  5519. // 删除设计
  5520. async deleteDesign(designId) {
  5521. return await apiClient.request(`/api/design/${designId}`, {
  5522. method: 'DELETE'
  5523. });
  5524. },
  5525. // 获取可用颜色列表
  5526. async getColors() {
  5527. return await apiClient.request('/api/design/colors');
  5528. },
  5529. // 获取可用材质列表
  5530. async getMaterials() {
  5531. return await apiClient.request('/api/design/materials');
  5532. },
  5533. // 保存配色方案
  5534. async saveColorScheme(schemeData) {
  5535. return await apiClient.request('/api/design/color-scheme', {
  5536. method: 'POST',
  5537. body: JSON.stringify(schemeData)
  5538. });
  5539. },
  5540. // 获取用户配色方案列表
  5541. async getColorSchemes() {
  5542. return await apiClient.request('/api/design/color-schemes');
  5543. }
  5544. };
  5545. // AI推荐模块接口
  5546. const AIAPI = {
  5547. // AI配色推荐
  5548. async getColorRecommendations(params) {
  5549. return await apiClient.request('/api/ai/recommend/colors', {
  5550. method: 'POST',
  5551. body: JSON.stringify(params)
  5552. });
  5553. },
  5554. // AI风格推荐
  5555. async getStyleRecommendations(params) {
  5556. return await apiClient.request('/api/ai/recommend/style', {
  5557. method: 'POST',
  5558. body: JSON.stringify(params)
  5559. });
  5560. },
  5561. // AI设计助手对话
  5562. async chat(message, context = {}) {
  5563. return await apiClient.request('/api/ai/chat', {
  5564. method: 'POST',
  5565. body: JSON.stringify({
  5566. message,
  5567. context
  5568. })
  5569. });
  5570. }
  5571. };
  5572. // 社区模块接口
  5573. const CommunityAPI = {
  5574. // 发布作品到社区
  5575. async publishWork(workData) {
  5576. return await apiClient.request('/api/community/publish', {
  5577. method: 'POST',
  5578. body: JSON.stringify(workData)
  5579. });
  5580. },
  5581. // 获取社区作品列表
  5582. async getWorks(params = {}) {
  5583. const queryString = new URLSearchParams(params).toString();
  5584. return await apiClient.request(`/api/community/works?${queryString}`);
  5585. },
  5586. // 获取作品详情
  5587. async getWorkDetail(workId) {
  5588. return await apiClient.request(`/api/community/works/${workId}`);
  5589. },
  5590. // 更新作品信息
  5591. async updateWork(workId, workData) {
  5592. return await apiClient.request(`/api/community/works/${workId}`, {
  5593. method: 'PUT',
  5594. body: JSON.stringify(workData)
  5595. });
  5596. },
  5597. // 删除作品
  5598. async deleteWork(workId) {
  5599. return await apiClient.request(`/api/community/works/${workId}`, {
  5600. method: 'DELETE'
  5601. });
  5602. },
  5603. // 点赞作品
  5604. async likeWork(workId) {
  5605. return await apiClient.request(`/api/community/works/${workId}/like`, {
  5606. method: 'POST'
  5607. });
  5608. },
  5609. // 评论作品
  5610. async commentWork(workId, content, replyTo = null) {
  5611. return await apiClient.request(`/api/community/works/${workId}/comment`, {
  5612. method: 'POST',
  5613. body: JSON.stringify({
  5614. content,
  5615. reply_to: replyTo
  5616. })
  5617. });
  5618. },
  5619. // 获取作品评论列表
  5620. async getWorkComments(workId, params = {}) {
  5621. const queryString = new URLSearchParams(params).toString();
  5622. return await apiClient.request(`/api/community/works/${workId}/comments?${queryString}`);
  5623. },
  5624. // 收藏作品
  5625. async collectWork(workId) {
  5626. return await apiClient.request(`/api/community/works/${workId}/collect`, {
  5627. method: 'POST'
  5628. });
  5629. },
  5630. // 下载作品设计文件
  5631. async downloadWork(workId) {
  5632. return await apiClient.request(`/api/community/works/${workId}/download`, {
  5633. method: 'POST'
  5634. });
  5635. },
  5636. // 关注用户
  5637. async followUser(userId) {
  5638. return await apiClient.request(`/api/community/follow/${userId}`, {
  5639. method: 'POST'
  5640. });
  5641. },
  5642. // 获取粉丝列表
  5643. async getFollowers(params = {}) {
  5644. const queryString = new URLSearchParams(params).toString();
  5645. return await apiClient.request(`/api/community/followers?${queryString}`);
  5646. },
  5647. // 获取关注列表
  5648. async getFollowing(params = {}) {
  5649. const queryString = new URLSearchParams(params).toString();
  5650. return await apiClient.request(`/api/community/following?${queryString}`);
  5651. }
  5652. };
  5653. // 文件上传接口
  5654. const UploadAPI = {
  5655. // 上传图片
  5656. async uploadImage(file, category = 'general', compress = true) {
  5657. const formData = new FormData();
  5658. formData.append('file', file);
  5659. formData.append('category', category);
  5660. formData.append('compress', compress);
  5661. return await apiClient.request('/api/upload/image', {
  5662. method: 'POST',
  5663. headers: {
  5664. // 不设置Content-Type,让浏览器自动设置multipart/form-data
  5665. ...authManager.getAuthHeaders()
  5666. },
  5667. body: formData
  5668. });
  5669. },
  5670. // 上传3D模型
  5671. async upload3DModel(file) {
  5672. const formData = new FormData();
  5673. formData.append('file', file);
  5674. return await apiClient.request('/api/upload/3d-model', {
  5675. method: 'POST',
  5676. headers: {
  5677. ...authManager.getAuthHeaders()
  5678. },
  5679. body: formData
  5680. });
  5681. },
  5682. // 批量上传文件
  5683. async uploadBatch(files) {
  5684. const formData = new FormData();
  5685. files.forEach((file, index) => {
  5686. formData.append('files', file);
  5687. });
  5688. return await apiClient.request('/api/upload/batch', {
  5689. method: 'POST',
  5690. headers: {
  5691. ...authManager.getAuthHeaders()
  5692. },
  5693. body: formData
  5694. });
  5695. }
  5696. };
  5697. // =========================== 业务逻辑层 ===========================
  5698. // 认证相关业务逻辑
  5699. const AuthService = {
  5700. // 用户注册
  5701. async register(userData) {
  5702. try {
  5703. showNotification('注册中', '正在创建您的账户...');
  5704. const response = await AuthAPI.register(userData);
  5705. if (response.code === 200) {
  5706. authManager.setAuth(response.data);
  5707. showNotification('注册成功', '欢迎加入FashionCraft!');
  5708. return response.data;
  5709. }
  5710. } catch (error) {
  5711. showNotification('注册失败', error.message || '注册过程中出现错误');
  5712. throw error;
  5713. }
  5714. },
  5715. // 用户登录
  5716. async login(credentials) {
  5717. try {
  5718. showNotification('登录中', '正在验证您的账户...');
  5719. const response = await AuthAPI.login(credentials);
  5720. if (response.code === 200) {
  5721. authManager.setAuth(response.data);
  5722. showNotification('登录成功', `欢迎回来,${response.data.username}!`);
  5723. // 登录成功后初始化用户数据
  5724. await this.initializeUserData();
  5725. return response.data;
  5726. }
  5727. } catch (error) {
  5728. showNotification('登录失败', error.message || '登录过程中出现错误');
  5729. throw error;
  5730. }
  5731. },
  5732. // 用户登出
  5733. async logout() {
  5734. try {
  5735. if (authManager.isAuthenticated()) {
  5736. await AuthAPI.logout();
  5737. }
  5738. } catch (error) {
  5739. console.warn('登出请求失败:', error);
  5740. } finally {
  5741. authManager.clearAuth();
  5742. showNotification('退出成功', '您已成功退出登录');
  5743. }
  5744. },
  5745. // 初始化用户数据
  5746. async initializeUserData() {
  5747. try {
  5748. // 并行获取用户相关数据
  5749. const [profile, designs] = await Promise.allSettled([
  5750. UserAPI.getProfile(),
  5751. DesignAPI.getDesignList({ page: 1, page_size: 10 })
  5752. ]);
  5753. if (profile.status === 'fulfilled' && profile.value.code === 200) {
  5754. authManager.user = profile.value.data;
  5755. localStorage.setItem('fashioncraft_user', JSON.stringify(profile.value.data));
  5756. }
  5757. if (designs.status === 'fulfilled' && designs.value.code === 200) {
  5758. // 可以在这里更新设计列表的UI
  5759. console.log('用户设计列表:', designs.value.data);
  5760. }
  5761. } catch (error) {
  5762. console.warn('初始化用户数据失败:', error);
  5763. }
  5764. }
  5765. };
  5766. // 设计相关业务逻辑
  5767. const DesignService = {
  5768. // 创建新设计
  5769. async createDesign(designData) {
  5770. try {
  5771. showNotification('创建设计', '正在创建新的设计项目...');
  5772. const response = await DesignAPI.createDesign(designData);
  5773. if (response.code === 200) {
  5774. showNotification('创建成功', '新设计项目已创建!');
  5775. return response.data;
  5776. }
  5777. } catch (error) {
  5778. showNotification('创建失败', error.message || '创建设计时出现错误');
  5779. throw error;
  5780. }
  5781. },
  5782. // 保存设计
  5783. async saveDesign(designId, designData) {
  5784. try {
  5785. showNotification('保存中', '正在保存您的设计...');
  5786. const response = await DesignAPI.updateDesign(designId, designData);
  5787. if (response.code === 200) {
  5788. showNotification('保存成功', '设计已保存');
  5789. return response.data;
  5790. }
  5791. } catch (error) {
  5792. showNotification('保存失败', error.message || '保存设计时出现错误');
  5793. throw error;
  5794. }
  5795. },
  5796. // 保存配色方案
  5797. async saveColorScheme(schemeData) {
  5798. try {
  5799. const response = await DesignAPI.saveColorScheme(schemeData);
  5800. if (response.code === 200) {
  5801. showNotification('保存成功', `配色方案 "${schemeData.scheme_name}" 已保存`);
  5802. return response.data;
  5803. }
  5804. } catch (error) {
  5805. showNotification('保存失败', error.message || '保存配色方案时出现错误');
  5806. throw error;
  5807. }
  5808. }
  5809. };
  5810. // AI推荐相关业务逻辑
  5811. const AIService = {
  5812. // 获取AI配色推荐
  5813. async getColorRecommendations(params) {
  5814. try {
  5815. showNotification('AI分析中', '正在为您生成配色建议...');
  5816. const response = await AIAPI.getColorRecommendations(params);
  5817. if (response.code === 200) {
  5818. showNotification('推荐完成', 'AI配色方案已生成!');
  5819. return response.data;
  5820. }
  5821. } catch (error) {
  5822. showNotification('推荐失败', error.message || 'AI服务暂时不可用');
  5823. throw error;
  5824. }
  5825. },
  5826. // DeepSeek AI聊天
  5827. async chat(message, context = {}) {
  5828. try {
  5829. // 构建对话历史
  5830. const messages = [
  5831. {
  5832. role: "system",
  5833. content: `你是一个专业的AI时尚顾问,专门为用户提供服装搭配、配色建议、风格分析等时尚相关的专业建议。
  5834. 请用专业但友好的语气回答用户问题,并尽可能提供具体实用的建议。
  5835. 为了让回答更美观易读,请在回答中使用以下格式:
  5836. - 使用 **粗体** 来突出重点
  5837. - 使用 *斜体* 来表示强调
  5838. - 使用数字列表(1. 2. 3.)来组织步骤
  5839. - 使用项目符号(- 或 •)来列举要点
  5840. - 使用 > 引用格式来提供重要提示
  5841. - 使用 [重要] [建议] [提示] 标签来标记不同类型信息
  5842. - 适当使用时尚表情符号:✨💡🎨👔👗👠💄👜
  5843. - 涉及颜色时可以使用十六进制代码如 #FF6B6B #Navy #Black
  5844. 示例格式:
  5845. **时尚搭配建议** ✨
  5846. [重要] 根据您的需求,我为您准备了专业建议:
  5847. 1. **上装选择**:推荐 #1E3A8A 海军蓝西装 👔
  5848. 2. **配饰搭配**:选择经典皮包 👜 和舒适高跟鞋 👠
  5849. > 💡 配色小贴士:颜色搭配要和谐统一,不超过3个主色调
  5850. • 春季推荐:清新淡雅色调 🌸
  5851. • 商务场合:沉稳大气配色
  5852. • 约会装扮:温柔浪漫风格 💄
  5853. [建议] 根据场合选择合适的风格最重要!
  5854. 希望这些专业建议对您有帮助!`
  5855. }
  5856. ];
  5857. // 添加对话历史上下文
  5858. if (context.conversation_history && context.conversation_history.length > 0) {
  5859. context.conversation_history.forEach(chat => {
  5860. if (chat.type === 'user') {
  5861. messages.push({
  5862. role: "user",
  5863. content: chat.text
  5864. });
  5865. } else if (chat.type === 'ai') {
  5866. messages.push({
  5867. role: "assistant",
  5868. content: chat.text
  5869. });
  5870. }
  5871. });
  5872. }
  5873. // 添加当前设计上下文
  5874. let contextMessage = message;
  5875. if (context.current_design) {
  5876. contextMessage += `\n\n当前设计信息:选中部位:${context.current_design.selected_part},颜色配置:${JSON.stringify(context.current_design.colors)}`;
  5877. }
  5878. // 添加当前用户消息
  5879. messages.push({
  5880. role: "user",
  5881. content: contextMessage
  5882. });
  5883. // 调用DeepSeek API
  5884. const response = await fetch('https://api.deepseek.com/chat/completions', {
  5885. method: 'POST',
  5886. headers: {
  5887. 'Content-Type': 'application/json',
  5888. 'Authorization': 'Bearer sk-dc7294eb7e274967afa7ca6c4c1cc367'
  5889. },
  5890. body: JSON.stringify({
  5891. model: "deepseek-chat",
  5892. messages: messages,
  5893. stream: false,
  5894. temperature: 0.7,
  5895. max_tokens: 1000
  5896. })
  5897. });
  5898. if (!response.ok) {
  5899. throw new Error(`DeepSeek API请求失败: ${response.status}`);
  5900. }
  5901. const data = await response.json();
  5902. if (data.choices && data.choices.length > 0) {
  5903. const aiResponse = data.choices[0].message.content;
  5904. // 返回格式化的响应
  5905. return {
  5906. response: aiResponse,
  5907. suggestions: this.extractSuggestions(aiResponse),
  5908. conversation_id: `deepseek_${Date.now()}`
  5909. };
  5910. } else {
  5911. throw new Error('DeepSeek API返回格式异常');
  5912. }
  5913. } catch (error) {
  5914. console.error('DeepSeek API调用失败:', error);
  5915. // 回退到本地生成的回复
  5916. const fallbackResponse = this.generateFallbackResponse(message);
  5917. return {
  5918. response: fallbackResponse,
  5919. suggestions: [],
  5920. conversation_id: `fallback_${Date.now()}`
  5921. };
  5922. }
  5923. },
  5924. // 从AI回复中提取建议
  5925. extractSuggestions(response) {
  5926. const suggestions = [];
  5927. // 简单的关键词检测来提取建议
  5928. if (response.includes('颜色') || response.includes('配色')) {
  5929. suggestions.push({
  5930. type: 'color',
  5931. content: {
  5932. colors: ['#1E3A8A', '#FFFFFF', '#EF4444'] // 示例颜色
  5933. },
  5934. reason: '基于AI分析推荐的配色方案'
  5935. });
  5936. }
  5937. return suggestions;
  5938. },
  5939. // 生成回退回复
  5940. generateFallbackResponse(message) {
  5941. const fallbackResponses = [
  5942. '作为您的时尚顾问,我建议您考虑颜色搭配的和谐性,选择适合您肤色和身材的款式。',
  5943. '时尚搭配的关键在于平衡,建议您从基础款开始,逐步添加个性化元素。',
  5944. '根据您的需求,我推荐选择经典而不失时尚感的单品,这样既实用又有品味。',
  5945. '搭配建议:注重色彩层次和材质对比,这能让整体造型更加出彩。'
  5946. ];
  5947. return fallbackResponses[Math.floor(Math.random() * fallbackResponses.length)];
  5948. }
  5949. };
  5950. // 文件上传相关业务逻辑
  5951. const UploadService = {
  5952. // 上传图片
  5953. async uploadImage(file, category = 'general') {
  5954. try {
  5955. // 检查文件大小
  5956. if (file.size > 50 * 1024 * 1024) { // 50MB
  5957. throw new Error('文件大小不能超过50MB');
  5958. }
  5959. // 检查文件类型
  5960. const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
  5961. if (!allowedTypes.includes(file.type)) {
  5962. throw new Error('不支持的文件格式,请选择JPG、PNG、GIF或WebP格式的图片');
  5963. }
  5964. showNotification('上传中', `正在上传 ${file.name}...`);
  5965. const response = await UploadAPI.uploadImage(file, category);
  5966. if (response.code === 200) {
  5967. showNotification('上传成功', '图片已成功上传!');
  5968. return response.data;
  5969. }
  5970. } catch (error) {
  5971. showNotification('上传失败', error.message || '上传图片时出现错误');
  5972. throw error;
  5973. }
  5974. },
  5975. // 批量上传文件
  5976. async uploadBatch(files) {
  5977. try {
  5978. if (files.length > 10) {
  5979. throw new Error('一次最多只能上传10个文件');
  5980. }
  5981. showNotification('批量上传', `正在上传 ${files.length} 个文件...`);
  5982. const response = await UploadAPI.uploadBatch(files);
  5983. if (response.code === 200) {
  5984. showNotification('上传完成', `成功上传 ${response.data.total} 个文件!`);
  5985. return response.data;
  5986. }
  5987. } catch (error) {
  5988. showNotification('上传失败', error.message || '批量上传时出现错误');
  5989. throw error;
  5990. }
  5991. }
  5992. };
  5993. // =========================== 初始化 ===========================
  5994. // 应用初始化
  5995. async function initializeApp() {
  5996. try {
  5997. // 获取系统配置
  5998. const configResponse = await SystemAPI.getConfig();
  5999. if (configResponse.code === 200) {
  6000. console.log('系统配置:', configResponse.data);
  6001. }
  6002. // 如果用户已登录,初始化用户数据
  6003. if (authManager.isAuthenticated()) {
  6004. await AuthService.initializeUserData();
  6005. console.log('用户已登录:', authManager.user);
  6006. }
  6007. console.log('应用初始化完成');
  6008. } catch (error) {
  6009. console.warn('应用初始化部分失败:', error);
  6010. }
  6011. }
  6012. // =========================== 原有功能代码 ===========================
  6013. // 全局变量
  6014. let currentSlide = 0;
  6015. let slideInterval;
  6016. let selectedColor = '#ff6b6b';
  6017. // 页面初始化
  6018. document.addEventListener('DOMContentLoaded', function() {
  6019. // 检查用户登录状态
  6020. checkAuthStatus();
  6021. // 初始化AI消息格式化
  6022. initializeAIMessageFormatting();
  6023. });
  6024. // 初始化AI消息格式化
  6025. function initializeAIMessageFormatting() {
  6026. // 格式化所有现有的AI消息
  6027. setTimeout(() => {
  6028. const aiMessages = document.querySelectorAll('.ai-message .message-text.ai-formatted');
  6029. aiMessages.forEach(messageElement => {
  6030. const originalText = messageElement.innerHTML;
  6031. messageElement.innerHTML = formatAIText(originalText);
  6032. });
  6033. }, 100);
  6034. }
  6035. // 检查登录状态
  6036. function checkAuthStatus() {
  6037. const isLoggedIn = authManager.isAuthenticated();
  6038. if (isLoggedIn) {
  6039. // 用户已登录,显示主应用
  6040. showMainApp();
  6041. } else {
  6042. // 用户未登录,显示登录页面
  6043. showAuthScreen();
  6044. }
  6045. }
  6046. // 显示主应用
  6047. function showMainApp() {
  6048. document.getElementById('auth-screen').style.display = 'none';
  6049. document.getElementById('main-app').style.display = 'block';
  6050. // 初始化主应用功能
  6051. initBannerSlider();
  6052. initNavigation();
  6053. initInteractions();
  6054. // 初始化API服务
  6055. initializeApp();
  6056. }
  6057. // 显示登录页面
  6058. function showAuthScreen() {
  6059. document.getElementById('auth-screen').style.display = 'flex';
  6060. document.getElementById('main-app').style.display = 'none';
  6061. }
  6062. // 轮播图功能
  6063. function initBannerSlider() {
  6064. const slider = document.getElementById('bannerSlider');
  6065. const indicators = document.querySelectorAll('.indicator');
  6066. const slides = document.querySelectorAll('.banner-slide');
  6067. // 自动播放
  6068. slideInterval = setInterval(nextSlide, 4000);
  6069. // 指示器点击事件
  6070. indicators.forEach((indicator, index) => {
  6071. indicator.addEventListener('click', () => {
  6072. goToSlide(index);
  6073. });
  6074. });
  6075. // 轮播图点击跳转事件
  6076. slides.forEach((slide, index) => {
  6077. slide.addEventListener('click', () => {
  6078. bannerClick(index);
  6079. });
  6080. });
  6081. // 鼠标悬停暂停
  6082. slider.addEventListener('mouseenter', () => {
  6083. clearInterval(slideInterval);
  6084. });
  6085. slider.addEventListener('mouseleave', () => {
  6086. slideInterval = setInterval(nextSlide, 4000);
  6087. });
  6088. }
  6089. function nextSlide() {
  6090. currentSlide = (currentSlide + 1) % 3;
  6091. updateSlider();
  6092. }
  6093. function goToSlide(index) {
  6094. currentSlide = index;
  6095. updateSlider();
  6096. }
  6097. function updateSlider() {
  6098. const slider = document.getElementById('bannerSlider');
  6099. const indicators = document.querySelectorAll('.indicator');
  6100. slider.style.transform = `translateX(-${currentSlide * 100}%)`;
  6101. indicators.forEach((indicator, index) => {
  6102. indicator.classList.toggle('active', index === currentSlide);
  6103. });
  6104. }
  6105. // 轮播图点击跳转功能
  6106. function bannerClick(index) {
  6107. // 根据轮播图索引跳转到不同页面
  6108. switch(index) {
  6109. case 0: // 春季新品发布
  6110. switchPage('design');
  6111. // 更新导航状态
  6112. updateNavigation('design');
  6113. showNotification('春季新品', '欢迎查看春季新品系列!');
  6114. break;
  6115. case 1: // AI智能搭配
  6116. showModal('AI智能搭配', '基于您的喜好,我们为您推荐了以下服装', '查看推荐', () => {
  6117. closeModal(); // 关闭模态框
  6118. switchPage('ar');
  6119. updateNavigation('ar');
  6120. });
  6121. break;
  6122. case 2: // 设计大赛进行中
  6123. showModal('设计大赛', '设计大赛正在进行中,立即参与!', '查看详情', () => {
  6124. closeModal(); // 关闭模态框
  6125. switchPage('community');
  6126. updateNavigation('community');
  6127. });
  6128. break;
  6129. default:
  6130. break;
  6131. }
  6132. }
  6133. // 更新导航状态的辅助函数
  6134. function updateNavigation(page) {
  6135. const navItems = document.querySelectorAll('.nav-item');
  6136. navItems.forEach(nav => nav.classList.remove('active'));
  6137. document.querySelector(`.nav-item[data-page="${page}"]`).classList.add('active');
  6138. }
  6139. // 导航功能
  6140. function initNavigation() {
  6141. const navItems = document.querySelectorAll('.nav-item');
  6142. navItems.forEach(item => {
  6143. item.addEventListener('click', () => {
  6144. const page = item.dataset.page;
  6145. switchPage(page);
  6146. // 更新导航状态
  6147. navItems.forEach(nav => nav.classList.remove('active'));
  6148. item.classList.add('active');
  6149. });
  6150. });
  6151. }
  6152. function switchPage(pageId) {
  6153. const pages = document.querySelectorAll('.page');
  6154. pages.forEach(page => {
  6155. page.style.display = 'none';
  6156. });
  6157. const targetPage = document.getElementById(pageId + '-page');
  6158. if (targetPage) {
  6159. targetPage.style.display = 'block';
  6160. targetPage.classList.add('fade-in');
  6161. setTimeout(() => {
  6162. targetPage.classList.remove('fade-in');
  6163. }, 300);
  6164. }
  6165. }
  6166. // 交互功能
  6167. function initInteractions() {
  6168. // 添加脉搏动画
  6169. const style = document.createElement('style');
  6170. style.textContent = `
  6171. @keyframes pulse {
  6172. 0%, 100% { transform: scale(1); }
  6173. 50% { transform: scale(1.1); }
  6174. }
  6175. `;
  6176. document.head.appendChild(style);
  6177. }
  6178. // 模态框功能
  6179. function showDesignModal() {
  6180. showModal('开始设计', '选择你想要设计的服装类型', '开始', startDesign);
  6181. }
  6182. function showModal(title, text, actionText = '开始', actionCallback = startDesign) {
  6183. const modal = document.getElementById('modal');
  6184. const modalTitle = document.getElementById('modalTitle');
  6185. const modalText = document.getElementById('modalText');
  6186. const primaryBtn = document.querySelector('.modal-actions .btn-primary');
  6187. modalTitle.textContent = title;
  6188. modalText.textContent = text;
  6189. primaryBtn.textContent = actionText;
  6190. primaryBtn.onclick = actionCallback;
  6191. modal.style.display = 'flex';
  6192. document.body.style.overflow = 'hidden';
  6193. }
  6194. function closeModal() {
  6195. const modal = document.getElementById('modal');
  6196. modal.style.display = 'none';
  6197. document.body.style.overflow = 'auto';
  6198. }
  6199. function startDesign() {
  6200. closeModal();
  6201. switchPage('design');
  6202. // 更新导航状态
  6203. const navItems = document.querySelectorAll('.nav-item');
  6204. navItems.forEach(nav => nav.classList.remove('active'));
  6205. document.querySelector('.nav-item[data-page="design"]').classList.add('active');
  6206. showNotification('开始设计', '欢迎来到设计中心!');
  6207. }
  6208. // 作品详情
  6209. function showWorkDetail(title) {
  6210. showNotification('作品详情', `正在查看《${title}》的详细信息`);
  6211. }
  6212. // AI推荐引擎相关全局变量
  6213. let aiChatHistory = [];
  6214. let isVoiceRecording = false;
  6215. let currentRecommendationScheme = 'scheme1';
  6216. // AI推荐引擎功能
  6217. function openAIChat(type) {
  6218. const modal = document.getElementById('aiChatModal');
  6219. const subtitle = document.getElementById('aiChatSubtitle');
  6220. const quickCommands = document.getElementById('aiQuickCommands');
  6221. modal.style.display = 'flex';
  6222. document.body.style.overflow = 'hidden';
  6223. // 根据类型设置不同的对话主题
  6224. switch(type) {
  6225. case 'occasion':
  6226. subtitle.textContent = '场合搭配专家为您服务...';
  6227. showAIMessage('我来帮您根据不同场合设计完美搭配!请告诉我您要参加什么场合?');
  6228. break;
  6229. case 'color':
  6230. subtitle.textContent = '配色大师为您分析...';
  6231. showAIMessage('专业配色分析师为您服务!我可以根据您的喜好和肤色,推荐最适合的颜色组合。');
  6232. break;
  6233. case 'style':
  6234. subtitle.textContent = '风格顾问在线中...';
  6235. showAIMessage('让我来分析您的个人风格!请描述一下您喜欢的穿衣风格,或者上传一张照片。');
  6236. break;
  6237. case 'free':
  6238. subtitle.textContent = '自由对话模式中...';
  6239. showAIMessage('有任何时尚相关的问题都可以问我哦!无论是搭配建议、流行趋势还是设计灵感。');
  6240. break;
  6241. }
  6242. // 隐藏快捷指令(进入对话状态)
  6243. quickCommands.style.display = 'none';
  6244. }
  6245. function closeAIChat() {
  6246. const modal = document.getElementById('aiChatModal');
  6247. modal.style.display = 'none';
  6248. document.body.style.overflow = 'auto';
  6249. // 重置快捷指令显示
  6250. const quickCommands = document.getElementById('aiQuickCommands');
  6251. quickCommands.style.display = 'flex';
  6252. }
  6253. // 文本格式化函数
  6254. function formatAIText(text) {
  6255. // 处理换行
  6256. text = text.replace(/\n/g, '<br>');
  6257. // 处理粗体 **text**
  6258. text = text.replace(/\*\*(.*?)\*\*/g, '<strong class="ai-bold">$1</strong>');
  6259. // 处理斜体 *text*
  6260. text = text.replace(/\*(.*?)\*/g, '<em class="ai-italic">$1</em>');
  6261. // 处理数字列表 1. 2. 3.
  6262. text = text.replace(/^(\d+)\.\s(.+)$/gm, '<div class="ai-list-item"><span class="ai-list-number">$1.</span> <span class="ai-list-content">$2</span></div>');
  6263. // 处理项目符号列表 - •
  6264. text = text.replace(/^[-•]\s(.+)$/gm, '<div class="ai-list-item"><span class="ai-bullet">•</span> <span class="ai-list-content">$1</span></div>');
  6265. // 处理引用 > text
  6266. text = text.replace(/^>\s(.+)$/gm, '<div class="ai-quote"><span class="ai-quote-icon">💡</span> $1</div>');
  6267. // 处理分隔线
  6268. text = text.replace(/^---$/gm, '<div class="ai-divider"></div>');
  6269. // 处理特殊标签
  6270. text = text.replace(/\[重要\]/g, '<span class="ai-tag ai-tag-important">重要</span>');
  6271. text = text.replace(/\[建议\]/g, '<span class="ai-tag ai-tag-suggestion">建议</span>');
  6272. text = text.replace(/\[提示\]/g, '<span class="ai-tag ai-tag-tip">提示</span>');
  6273. // 处理颜色标签 #颜色
  6274. text = text.replace(/#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})/g, '<span class="ai-color-tag" style="background-color: #$1; color: white; padding: 2px 6px; border-radius: 4px; font-size: 12px; box-shadow: 0 2px 4px rgba(0,0,0,0.2);">#$1</span>');
  6275. // 处理表情包增强
  6276. text = text.replace(/✨/g, '<span class="ai-sparkle">✨</span>');
  6277. text = text.replace(/💡/g, '<span class="ai-idea">💡</span>');
  6278. text = text.replace(/🎨/g, '<span class="ai-art">🎨</span>');
  6279. text = text.replace(/👔/g, '<span class="ai-suit">👔</span>');
  6280. text = text.replace(/👗/g, '<span class="ai-dress">👗</span>');
  6281. text = text.replace(/👠/g, '<span class="ai-heels">👠</span>');
  6282. text = text.replace(/💄/g, '<span class="ai-makeup">💄</span>');
  6283. text = text.replace(/👜/g, '<span class="ai-bag">👜</span>');
  6284. // 添加段落间距
  6285. text = text.replace(/(<br>\s*){2,}/g, '<div class="ai-paragraph-break"></div>');
  6286. return text;
  6287. }
  6288. function showAIMessage(text) {
  6289. const messagesContainer = document.getElementById('aiChatMessages');
  6290. const messageDiv = document.createElement('div');
  6291. messageDiv.className = 'ai-message';
  6292. const currentTime = new Date().toLocaleTimeString('zh-CN', {
  6293. hour: '2-digit',
  6294. minute: '2-digit'
  6295. });
  6296. // 格式化文本
  6297. const formattedText = formatAIText(text);
  6298. messageDiv.innerHTML = `
  6299. <div class="message-avatar">🤖</div>
  6300. <div class="message-content">
  6301. <div class="message-text ai-formatted">${formattedText}</div>
  6302. <div class="message-time">${currentTime}</div>
  6303. </div>
  6304. `;
  6305. messagesContainer.appendChild(messageDiv);
  6306. messagesContainer.scrollTop = messagesContainer.scrollHeight;
  6307. // 添加打字机效果和渐入动画
  6308. const messageText = messageDiv.querySelector('.message-text');
  6309. const messageAvatar = messageDiv.querySelector('.message-avatar');
  6310. messageDiv.style.opacity = '0';
  6311. messageDiv.style.transform = 'translateY(20px) scale(0.95)';
  6312. setTimeout(() => {
  6313. messageDiv.style.transition = 'all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1)';
  6314. messageDiv.style.opacity = '1';
  6315. messageDiv.style.transform = 'translateY(0) scale(1)';
  6316. // 头像呼吸效果
  6317. messageAvatar.style.animation = 'avatarPulse 0.6s ease-out';
  6318. }, 150);
  6319. // 为列表项和引用块添加延迟动画
  6320. setTimeout(() => {
  6321. const animatedElements = messageDiv.querySelectorAll('.ai-list-item, .ai-quote');
  6322. animatedElements.forEach((element, index) => {
  6323. element.style.opacity = '0';
  6324. element.style.transform = 'translateX(-20px)';
  6325. element.style.transition = 'all 0.3s ease';
  6326. setTimeout(() => {
  6327. element.style.opacity = '1';
  6328. element.style.transform = 'translateX(0)';
  6329. }, index * 100);
  6330. });
  6331. }, 200);
  6332. // 添加到对话历史
  6333. aiChatHistory.push({
  6334. type: 'ai',
  6335. text: text,
  6336. time: currentTime
  6337. });
  6338. }
  6339. function showUserMessage(text) {
  6340. const messagesContainer = document.getElementById('aiChatMessages');
  6341. const messageDiv = document.createElement('div');
  6342. messageDiv.className = 'user-message';
  6343. const currentTime = new Date().toLocaleTimeString('zh-CN', {
  6344. hour: '2-digit',
  6345. minute: '2-digit'
  6346. });
  6347. messageDiv.innerHTML = `
  6348. <div class="message-avatar">👤</div>
  6349. <div class="message-content">
  6350. <div class="message-text">${text}</div>
  6351. <div class="message-time">${currentTime}</div>
  6352. </div>
  6353. `;
  6354. messagesContainer.appendChild(messageDiv);
  6355. messagesContainer.scrollTop = messagesContainer.scrollHeight;
  6356. // 添加简洁的入场动画
  6357. messageDiv.style.opacity = '0';
  6358. messageDiv.style.transform = 'translateY(15px) scale(0.98)';
  6359. setTimeout(() => {
  6360. messageDiv.style.transition = 'all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)';
  6361. messageDiv.style.opacity = '1';
  6362. messageDiv.style.transform = 'translateY(0) scale(1)';
  6363. }, 50);
  6364. // 添加到对话历史
  6365. aiChatHistory.push({
  6366. type: 'user',
  6367. text: text,
  6368. time: currentTime
  6369. });
  6370. }
  6371. function showAILoadingMessage() {
  6372. const messagesContainer = document.getElementById('aiChatMessages');
  6373. const messageDiv = document.createElement('div');
  6374. messageDiv.className = 'ai-message loading-message';
  6375. messageDiv.id = 'ai-loading-message';
  6376. messageDiv.innerHTML = `
  6377. <div class="message-avatar">🤖</div>
  6378. <div class="message-content">
  6379. <div class="message-text">
  6380. <span class="loading-dots">DeepSeek AI正在思考中</span>
  6381. <span class="dots">...</span>
  6382. </div>
  6383. </div>
  6384. `;
  6385. messagesContainer.appendChild(messageDiv);
  6386. messagesContainer.scrollTop = messagesContainer.scrollHeight;
  6387. // 添加动画效果
  6388. const dots = messageDiv.querySelector('.dots');
  6389. let dotCount = 0;
  6390. const loadingInterval = setInterval(() => {
  6391. dotCount = (dotCount + 1) % 4;
  6392. dots.textContent = '.'.repeat(dotCount);
  6393. }, 500);
  6394. messageDiv.loadingInterval = loadingInterval;
  6395. }
  6396. function removeAILoadingMessage() {
  6397. const loadingMessage = document.getElementById('ai-loading-message');
  6398. if (loadingMessage) {
  6399. if (loadingMessage.loadingInterval) {
  6400. clearInterval(loadingMessage.loadingInterval);
  6401. }
  6402. loadingMessage.remove();
  6403. }
  6404. }
  6405. async function sendMessage() {
  6406. const input = document.getElementById('aiChatInput');
  6407. const message = input.value.trim();
  6408. if (!message) return;
  6409. // 显示用户消息
  6410. showUserMessage(message);
  6411. input.value = '';
  6412. // 显示加载指示器
  6413. showAILoadingMessage();
  6414. try {
  6415. // 构建上下文信息
  6416. const context = {
  6417. current_design: currentBodyPart && partColors ? {
  6418. selected_part: currentBodyPart,
  6419. colors: partColors
  6420. } : null,
  6421. conversation_history: aiChatHistory.slice(-5) // 保留最近5轮对话
  6422. };
  6423. // 调用真实的AI API
  6424. const aiResponse = await AIService.chat(message, context);
  6425. // 移除加载指示器
  6426. removeAILoadingMessage();
  6427. // 显示AI回复
  6428. showAIMessage(aiResponse.response);
  6429. // 处理AI建议
  6430. if (aiResponse.suggestions && aiResponse.suggestions.length > 0) {
  6431. setTimeout(() => {
  6432. aiResponse.suggestions.forEach(suggestion => {
  6433. if (suggestion.type === 'color') {
  6434. showAIMessage(`💡 配色建议:${suggestion.reason}`);
  6435. }
  6436. });
  6437. }, 1000);
  6438. }
  6439. // 保存对话历史
  6440. aiChatHistory.push({
  6441. user: message,
  6442. assistant: aiResponse.response,
  6443. timestamp: Date.now()
  6444. });
  6445. // 已移除自动跳转到推荐结果页面的功能
  6446. // 用户可以通过手动方式访问推荐功能
  6447. } catch (error) {
  6448. // 移除加载指示器
  6449. removeAILoadingMessage();
  6450. // 如果API调用失败,回退到模拟回复
  6451. setTimeout(() => {
  6452. const fallbackResponse = generateAIResponse(message);
  6453. showAIMessage(fallbackResponse);
  6454. if (shouldShowRecommendation(message)) {
  6455. setTimeout(() => {
  6456. showAIMessage('我已经为您准备了专属的搭配方案,点击查看详细推荐!');
  6457. setTimeout(() => {
  6458. openRecommendationResult();
  6459. }, 1000);
  6460. }, 2000);
  6461. }
  6462. }, 1000 + Math.random() * 2000);
  6463. }
  6464. }
  6465. async function sendQuickCommand(command) {
  6466. // 隐藏快捷指令
  6467. const quickCommands = document.getElementById('aiQuickCommands');
  6468. quickCommands.style.display = 'none';
  6469. // 发送快捷指令
  6470. showUserMessage(command);
  6471. // 显示加载指示器
  6472. showAILoadingMessage();
  6473. try {
  6474. // 构建上下文信息
  6475. const context = {
  6476. current_design: currentBodyPart && partColors ? {
  6477. selected_part: currentBodyPart,
  6478. colors: partColors
  6479. } : null,
  6480. conversation_history: aiChatHistory.slice(-5) // 保留最近5轮对话
  6481. };
  6482. // 调用DeepSeek AI API
  6483. const aiResponse = await AIService.chat(command, context);
  6484. // 移除加载指示器
  6485. removeAILoadingMessage();
  6486. // 显示AI回复
  6487. showAIMessage(aiResponse.response);
  6488. // 处理AI建议
  6489. if (aiResponse.suggestions && aiResponse.suggestions.length > 0) {
  6490. setTimeout(() => {
  6491. aiResponse.suggestions.forEach(suggestion => {
  6492. if (suggestion.type === 'color') {
  6493. showAIMessage(`💡 配色建议:${suggestion.reason}`);
  6494. }
  6495. });
  6496. }, 1000);
  6497. }
  6498. // 保存对话历史
  6499. aiChatHistory.push({
  6500. user: command,
  6501. assistant: aiResponse.response,
  6502. timestamp: Date.now()
  6503. });
  6504. // 检查是否需要显示推荐结果
  6505. if (shouldShowRecommendation(command)) {
  6506. setTimeout(() => {
  6507. showAIMessage('我为您精心准备了搭配方案,让我们来看看推荐结果!');
  6508. setTimeout(() => {
  6509. openRecommendationResult();
  6510. }, 1000);
  6511. }, 2000);
  6512. }
  6513. } catch (error) {
  6514. // 移除加载指示器
  6515. removeAILoadingMessage();
  6516. // 如果API调用失败,回退到模拟回复
  6517. setTimeout(() => {
  6518. const fallbackResponse = generateAIResponse(command);
  6519. showAIMessage(fallbackResponse);
  6520. if (shouldShowRecommendation(command)) {
  6521. setTimeout(() => {
  6522. showAIMessage('我为您精心准备了搭配方案,让我们来看看推荐结果!');
  6523. setTimeout(() => {
  6524. openRecommendationResult();
  6525. }, 1000);
  6526. }, 2000);
  6527. }
  6528. }, 1500);
  6529. }
  6530. }
  6531. function generateAIResponse(userMessage) {
  6532. const responses = {
  6533. '商务': [
  6534. '商务装搭配需要注重专业感和权威性。推荐选择深色西装,搭配白色或浅蓝色衬衫,以及经典的领带。',
  6535. '对于商务场合,建议选择海军蓝或深灰色作为主色调,这样既显稳重又不失现代感。'
  6536. ],
  6537. '休闲': [
  6538. '休闲装的核心是舒适与时尚的平衡。可以尝试牛仔裤搭配舒适的T恤或针织衫。',
  6539. '休闲风格可以更多地运用色彩层次,比如浅色系的组合会让人看起来更加放松自然。'
  6540. ],
  6541. '春季': [
  6542. '春季流行色彩偏向清新自然,推荐薄荷绿、樱花粉、天空蓝等颜色。',
  6543. '春天是万物复苏的季节,服装色彩也应该充满生机,浅色调和柔和的渐变色都是不错的选择。'
  6544. ],
  6545. '约会': [
  6546. '约会装要在优雅与个性之间找到平衡。推荐选择有设计感但不过分夸张的单品。',
  6547. '约会时的配色可以选择温暖的色调,比如粉色、桃色或者优雅的紫色系。'
  6548. ]
  6549. };
  6550. // 简单的关键词匹配
  6551. for (let keyword in responses) {
  6552. if (userMessage.includes(keyword)) {
  6553. const keywordResponses = responses[keyword];
  6554. return keywordResponses[Math.floor(Math.random() * keywordResponses.length)];
  6555. }
  6556. }
  6557. // 默认回复
  6558. const defaultResponses = [
  6559. '这是一个很有趣的想法!让我为您分析一下最适合的搭配方案。',
  6560. '根据您的需求,我建议从色彩搭配入手,创造出和谐统一的视觉效果。',
  6561. '很好的问题!时尚搭配的关键在于了解自己的风格定位和场合需求。',
  6562. '我理解您的想法,让我为您推荐一些专业的搭配建议。'
  6563. ];
  6564. return defaultResponses[Math.floor(Math.random() * defaultResponses.length)];
  6565. }
  6566. function shouldShowRecommendation(message) {
  6567. const triggerWords = ['搭配', '推荐', '建议', '方案', '帮我', '想要', '设计'];
  6568. return triggerWords.some(word => message.includes(word));
  6569. }
  6570. function handleChatInputKeypress(event) {
  6571. if (event.key === 'Enter') {
  6572. sendMessage();
  6573. }
  6574. }
  6575. // 多模态输入功能
  6576. function startVoiceInput() {
  6577. if (isVoiceRecording) {
  6578. stopVoiceInput();
  6579. return;
  6580. }
  6581. isVoiceRecording = true;
  6582. const button = event.target.closest('.input-tool');
  6583. button.style.background = 'rgba(255, 107, 107, 0.3)';
  6584. button.innerHTML = '<span class="tool-icon">⏸️</span>';
  6585. showNotification('语音输入', '正在录音中...');
  6586. // 模拟语音识别
  6587. setTimeout(() => {
  6588. stopVoiceInput();
  6589. const input = document.getElementById('aiChatInput');
  6590. input.value = '帮我搭配一套适合春天的休闲装';
  6591. showNotification('语音识别', '语音转换完成');
  6592. }, 3000);
  6593. }
  6594. function stopVoiceInput() {
  6595. isVoiceRecording = false;
  6596. const button = document.querySelector('.input-tool');
  6597. button.style.background = 'rgba(255,255,255,0.15)';
  6598. button.innerHTML = '<span class="tool-icon">🎤</span>';
  6599. }
  6600. function uploadImage() {
  6601. // 创建文件输入
  6602. const fileInput = document.createElement('input');
  6603. fileInput.type = 'file';
  6604. fileInput.accept = 'image/*';
  6605. fileInput.onchange = function(e) {
  6606. const file = e.target.files[0];
  6607. if (file) {
  6608. showNotification('图片识别', '正在分析您的穿搭照片...');
  6609. // 模拟图片识别
  6610. setTimeout(() => {
  6611. showUserMessage('📷 [已上传穿搭照片]');
  6612. setTimeout(() => {
  6613. showAIMessage('我看到您穿的是一套休闲风格的搭配!主要颜色是蓝色系,整体很清新。我可以为您推荐一些类似风格但更加时尚的搭配方案。');
  6614. }, 1500);
  6615. }, 2000);
  6616. }
  6617. };
  6618. fileInput.click();
  6619. }
  6620. function showEmoji() {
  6621. const emojis = ['😊', '👍', '❤️', '✨', '🎨', '👔', '👕', '👗', '💫', '🌟'];
  6622. const input = document.getElementById('aiChatInput');
  6623. const randomEmoji = emojis[Math.floor(Math.random() * emojis.length)];
  6624. input.value += randomEmoji;
  6625. input.focus();
  6626. }
  6627. // 悬浮球点击事件
  6628. document.addEventListener('DOMContentLoaded', function() {
  6629. const floatingBall = document.getElementById('aiFloatingBall');
  6630. if (floatingBall) {
  6631. floatingBall.addEventListener('click', function() {
  6632. openAIChat('free');
  6633. });
  6634. }
  6635. });
  6636. // 推荐结果页面功能
  6637. function openRecommendationResult() {
  6638. closeAIChat();
  6639. const modal = document.getElementById('aiRecommendationModal');
  6640. modal.style.display = 'flex';
  6641. document.body.style.overflow = 'hidden';
  6642. // 初始化推荐内容
  6643. updateRecommendationContent();
  6644. }
  6645. function closeRecommendation() {
  6646. const modal = document.getElementById('aiRecommendationModal');
  6647. modal.style.display = 'none';
  6648. document.body.style.overflow = 'auto';
  6649. }
  6650. function updateRecommendationContent() {
  6651. const schemes = {
  6652. 'scheme1': {
  6653. name: '经典商务风',
  6654. colors: ['#2c3e50', '#34495e', '#95a5a6'],
  6655. theory: [
  6656. {
  6657. icon: '🎯',
  6658. title: '主色调选择',
  6659. desc: '基于您的需求,选择了沉稳的深蓝色作为主色调,既显专业又不失现代感。'
  6660. },
  6661. {
  6662. icon: '🌈',
  6663. title: '色彩搭配',
  6664. desc: '采用单色调搭配法,深浅不同的蓝色系营造层次感和稳重感。'
  6665. },
  6666. {
  6667. icon: '✨',
  6668. title: '视觉效果',
  6669. desc: '整体造型简洁大方,适合商务场合,彰显专业形象。'
  6670. }
  6671. ]
  6672. },
  6673. 'scheme2': {
  6674. name: '春日清新风',
  6675. colors: ['#f39c12', '#e67e22', '#d35400'],
  6676. theory: [
  6677. {
  6678. icon: '🎯',
  6679. title: '季节特色',
  6680. desc: '春季专属的温暖色调,充满生机与活力,让人眼前一亮。'
  6681. },
  6682. {
  6683. icon: '🌈',
  6684. title: '暖色搭配',
  6685. desc: '橙色系的渐变搭配,营造温暖阳光的感觉,适合春日出行。'
  6686. },
  6687. {
  6688. icon: '✨',
  6689. title: '心理效应',
  6690. desc: '暖色调能够提升心情,增加亲和力和活力感。'
  6691. }
  6692. ]
  6693. },
  6694. 'scheme3': {
  6695. name: '优雅紫罗兰',
  6696. colors: ['#9b59b6', '#8e44ad', '#663399'],
  6697. theory: [
  6698. {
  6699. icon: '🎯',
  6700. title: '色彩心理',
  6701. desc: '紫色代表优雅与神秘,是富有创造力和艺术感的颜色选择。'
  6702. },
  6703. {
  6704. icon: '🌈',
  6705. title: '渐变层次',
  6706. desc: '紫色系的深浅渐变,创造出丰富的视觉层次和高级感。'
  6707. },
  6708. {
  6709. icon: '✨',
  6710. title: '独特气质',
  6711. desc: '紫色搭配能够突出个人品味,展现独特的时尚态度。'
  6712. }
  6713. ]
  6714. }
  6715. };
  6716. const currentScheme = schemes[currentRecommendationScheme];
  6717. const theoryContent = document.getElementById('colorTheoryContent');
  6718. theoryContent.innerHTML = currentScheme.theory.map(item => `
  6719. <div class="theory-card">
  6720. <div class="theory-icon">${item.icon}</div>
  6721. <div class="theory-text">
  6722. <h5>${item.title}</h5>
  6723. <p>${item.desc}</p>
  6724. </div>
  6725. </div>
  6726. `).join('');
  6727. }
  6728. function selectScheme(schemeId) {
  6729. currentRecommendationScheme = schemeId;
  6730. // 更新方案选择状态
  6731. const tabs = document.querySelectorAll('.scheme-tab');
  6732. tabs.forEach(tab => tab.classList.remove('active'));
  6733. event.target.classList.add('active');
  6734. // 更新推荐内容
  6735. updateRecommendationContent();
  6736. const schemeNames = {
  6737. 'scheme1': '经典商务风',
  6738. 'scheme2': '春日清新风',
  6739. 'scheme3': '优雅紫罗兰'
  6740. };
  6741. showNotification('方案切换', `已切换到${schemeNames[schemeId]}`);
  6742. }
  6743. function rotateModel(direction) {
  6744. const model = document.querySelector('.model-3d-display');
  6745. let currentRotation = parseInt(model.dataset.rotation || '0');
  6746. if (direction === 'left') {
  6747. currentRotation -= 90;
  6748. } else if (direction === 'right') {
  6749. currentRotation += 90;
  6750. }
  6751. model.style.transform = `rotateY(${currentRotation}deg)`;
  6752. model.dataset.rotation = currentRotation;
  6753. showNotification('3D旋转', `模型已旋转 ${direction === 'left' ? '向左' : '向右'} 90°`);
  6754. }
  6755. function resetModel() {
  6756. const model = document.querySelector('.model-3d-display');
  6757. model.style.transform = 'rotateY(0deg)';
  6758. model.dataset.rotation = '0';
  6759. showNotification('视角重置', '已重置到正面视角');
  6760. }
  6761. function shareRecommendation() {
  6762. showNotification('分享成功', '推荐方案已复制到剪贴板');
  6763. }
  6764. function saveRecommendation() {
  6765. showNotification('收藏成功', '推荐方案已保存到我的收藏');
  6766. }
  6767. function importToDesignCenter() {
  6768. closeRecommendation();
  6769. switchPage('design');
  6770. updateNavigation('design');
  6771. showNotification('导入成功', 'AI推荐方案已导入到设计中心');
  6772. }
  6773. function viewAIRecommendation(type) {
  6774. const recommendationTypes = {
  6775. 'business': '商务精英装',
  6776. 'casual': '休闲度假风'
  6777. };
  6778. showNotification('查看推荐', `正在查看${recommendationTypes[type]}推荐`);
  6779. setTimeout(() => {
  6780. openRecommendationResult();
  6781. }, 1000);
  6782. }
  6783. // 保持向后兼容
  6784. function showAIRecommend(style) {
  6785. openAIChat('free');
  6786. setTimeout(() => {
  6787. sendQuickCommand(`帮我搭配一套${style}风格的服装`);
  6788. }, 1000);
  6789. }
  6790. // 新版设计中心全局变量
  6791. let currentBodyPart = 'overall';
  6792. let currentMaterial = 'cotton';
  6793. let modelRotation = 0;
  6794. let partColors = {
  6795. 'overall': '#ff6b6b',
  6796. 'left-sleeve': '#ff6b6b',
  6797. 'right-sleeve': '#ff6b6b',
  6798. 'hood': '#ff6b6b',
  6799. 'body': '#ff6b6b'
  6800. };
  6801. let colorHistory = [];
  6802. // 3D模型控制函数
  6803. function rotateModel(direction) {
  6804. const model = document.getElementById('main3DModel');
  6805. if (direction === 'left') {
  6806. modelRotation -= 90;
  6807. } else if (direction === 'right') {
  6808. modelRotation += 90;
  6809. }
  6810. model.style.transform = `rotateY(${modelRotation}deg)`;
  6811. showNotification('3D旋转', `模型已旋转到 ${modelRotation}°`);
  6812. }
  6813. function resetModelView() {
  6814. modelRotation = 0;
  6815. const model = document.getElementById('main3DModel');
  6816. model.style.transform = 'rotateY(0deg)';
  6817. showNotification('视角重置', '已重置为正面视角');
  6818. }
  6819. // 分区控制面板
  6820. function toggleZonePanel() {
  6821. const content = document.querySelector('.zone-control-panel .panel-content');
  6822. const btn = document.querySelector('.expand-btn');
  6823. if (content.style.display === 'none') {
  6824. content.style.display = 'block';
  6825. btn.textContent = '⌄';
  6826. } else {
  6827. content.style.display = 'none';
  6828. btn.textContent = '⌃';
  6829. }
  6830. }
  6831. // 部位选择功能
  6832. function selectBodyPart(part) {
  6833. currentBodyPart = part;
  6834. // 更新Tab状态
  6835. const partTabs = document.querySelectorAll('.part-tab');
  6836. partTabs.forEach(tab => tab.classList.remove('active'));
  6837. document.querySelector(`[data-part="${part}"]`).classList.add('active');
  6838. // 更新当前部位显示
  6839. const partNames = {
  6840. 'overall': '整体',
  6841. 'left-sleeve': '左袖',
  6842. 'right-sleeve': '右袖',
  6843. 'hood': '帽子',
  6844. 'body': '身体'
  6845. };
  6846. document.getElementById('currentPartName').textContent = partNames[part];
  6847. document.getElementById('currentPartColor').style.background = partColors[part];
  6848. // 更新3D模型高亮效果
  6849. highlightBodyPart(part);
  6850. showNotification('部位选择', `已选择 ${partNames[part]} 部位`);
  6851. }
  6852. function highlightBodyPart(part) {
  6853. // 这里可以添加3D模型部位高亮的逻辑
  6854. const model = document.getElementById('main3DModel');
  6855. // 根据选择的部位显示不同的模型或高亮效果
  6856. switch(part) {
  6857. case 'overall':
  6858. model.textContent = '👕';
  6859. break;
  6860. case 'left-sleeve':
  6861. model.textContent = '👈👕';
  6862. break;
  6863. case 'right-sleeve':
  6864. model.textContent = '👕👉';
  6865. break;
  6866. case 'hood':
  6867. model.textContent = '🎩👕';
  6868. break;
  6869. case 'body':
  6870. model.textContent = '👕';
  6871. break;
  6872. }
  6873. }
  6874. // 颜色选择功能(增强版)
  6875. function selectColor(color) {
  6876. selectedColor = color;
  6877. partColors[currentBodyPart] = color;
  6878. // 更新颜色选择状态
  6879. const swatches = document.querySelectorAll('.color-swatch');
  6880. swatches.forEach(swatch => {
  6881. swatch.classList.remove('active');
  6882. if (swatch.getAttribute('data-color') === color) {
  6883. swatch.classList.add('active');
  6884. }
  6885. });
  6886. // 更新当前部位颜色指示器
  6887. document.getElementById('currentPartColor').style.background = color;
  6888. // 保存到历史记录
  6889. if (!colorHistory.includes(color)) {
  6890. colorHistory.push(color);
  6891. if (colorHistory.length > 10) {
  6892. colorHistory.shift();
  6893. }
  6894. }
  6895. // 更新3D模型颜色
  6896. const model = document.getElementById('main3DModel');
  6897. model.style.color = color;
  6898. showNotification('颜色应用', `${currentBodyPart} 部位已应用颜色 ${color}`);
  6899. }
  6900. // 自定义颜色选择
  6901. function selectCustomColor(color) {
  6902. selectColor(color);
  6903. }
  6904. function addCustomColor() {
  6905. const customColor = document.getElementById('customColorPicker').value;
  6906. selectColor(customColor);
  6907. showNotification('自定义颜色', '已添加自定义颜色到色盘');
  6908. }
  6909. // 色盘管理功能
  6910. function syncColorToAll() {
  6911. const currentColor = partColors[currentBodyPart];
  6912. Object.keys(partColors).forEach(part => {
  6913. partColors[part] = currentColor;
  6914. });
  6915. showNotification('颜色同步', '已将当前颜色同步到所有部位');
  6916. }
  6917. function showColorHistory() {
  6918. const historySection = document.getElementById('colorHistorySection');
  6919. if (historySection.style.display === 'none') {
  6920. historySection.style.display = 'block';
  6921. } else {
  6922. historySection.style.display = 'none';
  6923. }
  6924. }
  6925. // AI智能配色推荐
  6926. async function getAIColorRecommendation() {
  6927. try {
  6928. // 获取当前设计上下文
  6929. const params = {
  6930. style: 'casual', // 可以根据用户选择的风格来设置
  6931. base_color: partColors['overall'] || '#ff6b6b',
  6932. season: getCurrentSeason(),
  6933. occasion: 'daily'
  6934. };
  6935. const recommendations = await AIService.getColorRecommendations(params);
  6936. if (recommendations && recommendations.recommendations) {
  6937. showAIColorRecommendations(recommendations.recommendations);
  6938. }
  6939. } catch (error) {
  6940. // 如果API失败,显示预设的配色方案
  6941. showNotification('AI推荐', '正在为您准备智能配色方案...');
  6942. setTimeout(() => {
  6943. showPresetColorRecommendations();
  6944. }, 1500);
  6945. }
  6946. }
  6947. function getCurrentSeason() {
  6948. const month = new Date().getMonth() + 1;
  6949. if (month >= 3 && month <= 5) return 'spring';
  6950. if (month >= 6 && month <= 8) return 'summer';
  6951. if (month >= 9 && month <= 11) return 'autumn';
  6952. return 'winter';
  6953. }
  6954. function showAIColorRecommendations(recommendations) {
  6955. const recommendationHtml = `
  6956. <div id="aiColorModal" style="
  6957. position: fixed;
  6958. top: 0; left: 0;
  6959. width: 100%; height: 100%;
  6960. background: rgba(0,0,0,0.8);
  6961. display: flex;
  6962. justify-content: center;
  6963. align-items: center;
  6964. z-index: 10000;
  6965. ">
  6966. <div style="
  6967. background: white;
  6968. padding: 30px;
  6969. border-radius: 15px;
  6970. width: 90%;
  6971. max-width: 500px;
  6972. box-shadow: 0 20px 60px rgba(0,0,0,0.3);
  6973. max-height: 80vh;
  6974. overflow-y: auto;
  6975. ">
  6976. <h2 style="text-align: center; margin-bottom: 20px; color: #333;">🎨 AI智能配色推荐</h2>
  6977. <div id="recommendationsList">
  6978. ${recommendations.map((rec, index) => `
  6979. <div style="
  6980. border: 2px solid #eee;
  6981. border-radius: 10px;
  6982. padding: 15px;
  6983. margin-bottom: 15px;
  6984. cursor: pointer;
  6985. transition: all 0.3s;
  6986. " onclick="applyAIColorScheme(${JSON.stringify(rec.colors).replace(/"/g, '&quot;')}, '${rec.scheme_name}')">
  6987. <h3 style="margin: 0 0 10px 0; color: #333;">${rec.scheme_name}</h3>
  6988. <div style="display: flex; gap: 10px; margin-bottom: 10px;">
  6989. ${Object.values(rec.colors).map(color => `
  6990. <div style="
  6991. width: 40px;
  6992. height: 40px;
  6993. background: ${color};
  6994. border-radius: 50%;
  6995. border: 2px solid #fff;
  6996. box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  6997. "></div>
  6998. `).join('')}
  6999. </div>
  7000. <p style="margin: 0; font-size: 14px; color: #666;">${rec.theory ? rec.theory.description : '经典配色方案'}</p>
  7001. <div style="
  7002. background: linear-gradient(45deg, #4ecdc4, #44a08d);
  7003. color: white;
  7004. padding: 8px 15px;
  7005. border-radius: 5px;
  7006. text-align: center;
  7007. margin-top: 10px;
  7008. font-size: 14px;
  7009. ">点击应用此配色方案</div>
  7010. </div>
  7011. `).join('')}
  7012. </div>
  7013. <button onclick="closeAIColorModal()" style="
  7014. width: 100%;
  7015. padding: 12px;
  7016. background: #f0f0f0;
  7017. color: #333;
  7018. border: none;
  7019. border-radius: 8px;
  7020. font-size: 16px;
  7021. cursor: pointer;
  7022. margin-top: 10px;
  7023. ">关闭</button>
  7024. </div>
  7025. </div>
  7026. `;
  7027. document.body.insertAdjacentHTML('beforeend', recommendationHtml);
  7028. }
  7029. function showPresetColorRecommendations() {
  7030. const presetRecommendations = [
  7031. {
  7032. scheme_name: '商务精英',
  7033. colors: { s1: '#1E3A8A', t1: '#FFFFFF', y1: '#000000', z1: '#C0C0C0' },
  7034. theory: { description: '专业稳重,适合商务场合' }
  7035. },
  7036. {
  7037. scheme_name: '春日暖阳',
  7038. colors: { s1: '#FFA726', t1: '#FFE0B2', y1: '#FF8A65', z1: '#FFCC80' },
  7039. theory: { description: '温暖明亮,充满活力' }
  7040. },
  7041. {
  7042. scheme_name: '海洋清新',
  7043. colors: { s1: '#26C6DA', t1: '#B2EBF2', y1: '#4DD0E1', z1: '#80DEEA' },
  7044. theory: { description: '清新自然,如海风般舒适' }
  7045. }
  7046. ];
  7047. showAIColorRecommendations(presetRecommendations);
  7048. }
  7049. function applyAIColorScheme(colors, schemeName) {
  7050. // 应用AI推荐的配色方案
  7051. partColors = {
  7052. 'overall': colors.s1,
  7053. 's1': colors.s1,
  7054. 't1': colors.t1,
  7055. 'y1': colors.y1,
  7056. 'z1': colors.z1,
  7057. 'left-sleeve': colors.s1,
  7058. 'right-sleeve': colors.s1,
  7059. 'hood': colors.y1,
  7060. 'body': colors.t1
  7061. };
  7062. // 更新所有部位的颜色
  7063. Object.keys(partColors).forEach(part => {
  7064. if (part !== 'overall') {
  7065. updatePartImage(part, getCurrentColorName(partColors[part]));
  7066. }
  7067. });
  7068. // 刷新当前选中部位的显示
  7069. selectBodyPart(currentBodyPart);
  7070. closeAIColorModal();
  7071. showNotification('配色应用', `已应用"${schemeName}"配色方案`);
  7072. }
  7073. function getCurrentColorName(colorCode) {
  7074. // 将颜色代码转换为颜色名称(这里简化处理)
  7075. const colorMap = {
  7076. '#ff6b6b': '红色',
  7077. '#4ecdc4': '蒂芙尼蓝',
  7078. '#ffeaa7': '靓丽黄',
  7079. '#667eea': '长春花蓝',
  7080. '#1E3A8A': '深蓝色',
  7081. '#FFFFFF': '白色',
  7082. '#000000': '黑色',
  7083. '#C0C0C0': '银色',
  7084. '#FFA726': '橘色',
  7085. '#26C6DA': '蒂芙尼蓝'
  7086. };
  7087. return colorMap[colorCode] || '宝蓝色'; // 默认返回宝蓝色
  7088. }
  7089. function closeAIColorModal() {
  7090. const modal = document.getElementById('aiColorModal');
  7091. if (modal) modal.remove();
  7092. }
  7093. async function saveColorScheme() {
  7094. const schemeName = prompt('请输入配色方案名称:');
  7095. if (schemeName) {
  7096. try {
  7097. const schemeData = {
  7098. scheme_name: schemeName,
  7099. colors: {
  7100. s1: partColors['s1'] || partColors['overall'],
  7101. t1: partColors['t1'] || partColors['overall'],
  7102. y1: partColors['y1'] || partColors['overall'],
  7103. z1: partColors['z1'] || partColors['overall']
  7104. },
  7105. description: `用户自定义配色方案 - ${new Date().toLocaleDateString()}`
  7106. };
  7107. await DesignService.saveColorScheme(schemeData);
  7108. } catch (error) {
  7109. // 如果API调用失败,回退到本地存储
  7110. localStorage.setItem(`colorScheme_${Date.now()}`, JSON.stringify({
  7111. name: schemeName,
  7112. colors: partColors,
  7113. timestamp: Date.now()
  7114. }));
  7115. showNotification('方案保存', `配色方案 "${schemeName}" 已保存到本地`);
  7116. }
  7117. }
  7118. }
  7119. function loadColorScheme(schemeId) {
  7120. // 预设的配色方案
  7121. const schemes = {
  7122. 'scheme1': {
  7123. 'overall': '#ff6b6b',
  7124. 'left-sleeve': '#4ecdc4',
  7125. 'right-sleeve': '#4ecdc4',
  7126. 'hood': '#ffeaa7',
  7127. 'body': '#ff6b6b'
  7128. },
  7129. 'scheme2': {
  7130. 'overall': '#667eea',
  7131. 'left-sleeve': '#764ba2',
  7132. 'right-sleeve': '#764ba2',
  7133. 'hood': '#a29bfe',
  7134. 'body': '#667eea'
  7135. }
  7136. };
  7137. const scheme = schemes[schemeId];
  7138. if (scheme) {
  7139. partColors = {...scheme};
  7140. selectBodyPart(currentBodyPart); // 刷新显示
  7141. showNotification('方案加载', '配色方案已加载');
  7142. }
  7143. }
  7144. // 高级定制工具函数
  7145. function openAdvancedEmbroidery() {
  7146. showNotification('刺绣编辑器', `正在为 ${currentBodyPart} 部位开启高级刺绣编辑器`);
  7147. }
  7148. function openTextureSystem() {
  7149. showNotification('贴图系统', `正在为 ${currentBodyPart} 部位开启贴图编辑系统`);
  7150. }
  7151. function openPatternLibrary() {
  7152. showNotification('图案库', '正在打开海量设计素材库');
  7153. }
  7154. function openAIDesigner() {
  7155. getAIColorRecommendation();
  7156. }
  7157. // 服装切片图颜色切换功能
  7158. let currentSelectedPart = 'overall';
  7159. let availableColors = [
  7160. // 原有颜色
  7161. '蓝色', '粉色', '牛油果绿', '白色', '黑色', '橘色', '利灰',
  7162. // 新增颜色
  7163. '宝蓝色', '浅驼色', '测试色', '深灰绿', '深紫色', '深绿色',
  7164. '真朱', '睿智金', '红色', '萌萌绿', '蒂芙尼蓝', '长春花蓝',
  7165. '青紫', '靓丽黄'
  7166. ];
  7167. function selectClothingColor(colorName) {
  7168. console.log('选择颜色:', colorName, '当前部位:', currentSelectedPart);
  7169. if (currentSelectedPart === 'overall') {
  7170. // 整体颜色切换 - 所有部位
  7171. updateAllParts(colorName);
  7172. } else {
  7173. // 单独部位颜色切换
  7174. updateSinglePart(currentSelectedPart, colorName);
  7175. }
  7176. // 更新颜色选择状态
  7177. updateColorSwatchState(colorName);
  7178. showNotification('颜色切换', `已切换到${colorName}`);
  7179. }
  7180. function updateAllParts(colorName) {
  7181. const parts = ['s1', 't1', 'y1', 'z1'];
  7182. parts.forEach(part => {
  7183. updatePartImage(part, colorName);
  7184. });
  7185. }
  7186. function updateSinglePart(partName, colorName) {
  7187. updatePartImage(partName, colorName);
  7188. }
  7189. function updatePartImage(partName, colorName) {
  7190. const imgElement = document.querySelector(`#layer-${partName} img`);
  7191. if (imgElement) {
  7192. const imagePath = getImagePath(partName, colorName);
  7193. imgElement.src = imagePath;
  7194. console.log('更新图片:', partName, '→', imagePath);
  7195. }
  7196. }
  7197. function getImagePath(partName, colorName) {
  7198. // 路径映射:优先查找新切片图,再查找原切片图
  7199. function tryPath(basePath, partName, colorName) {
  7200. const partMap = {
  7201. 's1': 'S1.png',
  7202. 't1': 'T1.png',
  7203. 'y1': 'Y1.png',
  7204. 'z1': 'Z1.png'
  7205. };
  7206. const filename = partMap[partName];
  7207. if (!filename) return '';
  7208. // 检查是否在新切片图中
  7209. const newPath = `切片图/切片图/${colorName}/${filename}`;
  7210. // 特殊处理:浅驼色的文件名是小写的
  7211. if (colorName === '浅驼色') {
  7212. const lowercaseFilename = filename.toLowerCase();
  7213. return `切片图/切片图/${colorName}/${lowercaseFilename}`;
  7214. }
  7215. // 检查新切片图路径是否存在(这里我们假设新路径优先)
  7216. if (['宝蓝色', '浅驼色', '测试色', '深灰绿', '深紫色', '深绿色',
  7217. '真朱', '睿智金', '红色', '萌萌绿', '蒂芙尼蓝', '长春花蓝',
  7218. '青紫', '靓丽黄'].includes(colorName)) {
  7219. return newPath;
  7220. }
  7221. // 特殊处理:橘色和利灰只有T1和Y1
  7222. if ((colorName === '橘色' || colorName === '利灰') && (partName === 's1' || partName === 'z1')) {
  7223. // 如果橘色或利灰没有该部位,使用蓝色替代
  7224. return `切片图共7个/切片图共7个/蓝色/${filename}`;
  7225. }
  7226. // 返回原切片图路径
  7227. return `切片图共7个/切片图共7个/${colorName}/${filename}`;
  7228. }
  7229. return tryPath('', partName, colorName);
  7230. }
  7231. function selectBodyPart(partName) {
  7232. console.log('选择部位:', partName);
  7233. currentSelectedPart = partName;
  7234. // 更新按钮状态
  7235. document.querySelectorAll('.part-tab').forEach(tab => {
  7236. tab.classList.remove('active');
  7237. });
  7238. document.querySelector(`[data-part="${partName}"]`).classList.add('active');
  7239. // 更新当前部位名称显示
  7240. const partNames = {
  7241. 'overall': '整体',
  7242. 's1': 'S1部位',
  7243. 't1': 'T1部位',
  7244. 'y1': 'Y1部位',
  7245. 'z1': 'Z1部位'
  7246. };
  7247. document.getElementById('currentPartName').textContent = partNames[partName] || partName;
  7248. // 高亮显示选中部位
  7249. highlightSelectedPart(partName);
  7250. showNotification('部位选择', `已选择${partNames[partName]}`);
  7251. }
  7252. function highlightSelectedPart(partName) {
  7253. // 清除所有高亮
  7254. document.querySelectorAll('.part-image').forEach(img => {
  7255. img.classList.remove('highlighted', 'selected');
  7256. });
  7257. // 高亮选中部位
  7258. if (partName !== 'overall') {
  7259. const selectedImg = document.querySelector(`#layer-${partName} img`);
  7260. if (selectedImg) {
  7261. selectedImg.classList.add('selected');
  7262. }
  7263. }
  7264. }
  7265. function updateColorSwatchState(colorName) {
  7266. document.querySelectorAll('.color-swatch').forEach(swatch => {
  7267. swatch.classList.remove('active');
  7268. if (swatch.getAttribute('data-color') === colorName) {
  7269. swatch.classList.add('active');
  7270. }
  7271. });
  7272. }
  7273. // 兼容性函数(保持向后兼容)
  7274. function openColorPicker() {
  7275. showNotification('颜色设计器', '请使用下方的智能色盘系统');
  7276. }
  7277. function openPatternEditor() {
  7278. openPatternLibrary();
  7279. }
  7280. function openEmbroidery() {
  7281. openAdvancedEmbroidery();
  7282. }
  7283. function openAccessories() {
  7284. showNotification('配饰搭配', '配饰功能将在高级定制中提供');
  7285. }
  7286. // AR试穿功能
  7287. function selectScene(scene) {
  7288. const sceneNames = {
  7289. 'office': '办公场景',
  7290. 'date': '约会场景',
  7291. 'party': '派对场景',
  7292. 'casual': '休闲场景'
  7293. };
  7294. showNotification('场景切换', `已切换到${sceneNames[scene]}`);
  7295. }
  7296. // 社区功能
  7297. function likeWork(element) {
  7298. element.style.transform = 'scale(0.95)';
  7299. setTimeout(() => {
  7300. element.style.transform = 'scale(1)';
  7301. }, 150);
  7302. showNotification('点赞成功', '感谢你的支持!');
  7303. }
  7304. // 个人中心功能
  7305. function showMyDesigns() {
  7306. showNotification('我的设计稿', '查看你的所有设计作品');
  7307. }
  7308. function showTryOnHistory() {
  7309. showNotification('试穿历史', '查看你的试穿记录');
  7310. }
  7311. function showOrders() {
  7312. showNotification('订单管理', '查看你的订单状态');
  7313. }
  7314. function showCollections() {
  7315. showNotification('收藏夹', '查看你收藏的作品');
  7316. }
  7317. function showFollowers() {
  7318. showNotification('粉丝管理', '管理你的粉丝关系');
  7319. }
  7320. function showSettings() {
  7321. // 检查用户是否已登录
  7322. if (!authManager.isAuthenticated()) {
  7323. showLoginModal();
  7324. return;
  7325. }
  7326. // 加载用户信息到表单
  7327. const user = authManager.user;
  7328. if (user) {
  7329. document.getElementById('userName').value = user.nickname || user.username || '';
  7330. document.getElementById('userBio').value = user.bio || '';
  7331. document.getElementById('userLocation').value = user.location || '';
  7332. }
  7333. document.getElementById('settingsModal').style.display = 'block';
  7334. }
  7335. function closeSettingsModal() {
  7336. document.getElementById('settingsModal').style.display = 'none';
  7337. }
  7338. // 登录注册功能
  7339. function showLoginModal() {
  7340. showModal('用户登录', '请登录以使用完整功能', '立即登录', openLoginForm);
  7341. }
  7342. function openLoginForm() {
  7343. closeModal();
  7344. }
  7345. function showLoginForm() {
  7346. // 隐藏欢迎页面
  7347. document.getElementById('auth-screen').style.display = 'none';
  7348. const loginHtml = `
  7349. <div id="loginModal" style="
  7350. position: fixed;
  7351. top: 0; left: 0;
  7352. width: 100%; height: 100%;
  7353. background: rgba(0,0,0,0.8);
  7354. display: flex;
  7355. justify-content: center;
  7356. align-items: center;
  7357. z-index: 10000;
  7358. ">
  7359. <div style="
  7360. background: white;
  7361. padding: 30px;
  7362. border-radius: 15px;
  7363. width: 90%;
  7364. max-width: 400px;
  7365. box-shadow: 0 20px 60px rgba(0,0,0,0.3);
  7366. ">
  7367. <h2 style="text-align: center; margin-bottom: 20px; color: #333;">登录账户</h2>
  7368. <form id="loginForm" onsubmit="handleLogin(event)">
  7369. <div style="margin-bottom: 15px;">
  7370. <label style="display: block; margin-bottom: 5px; font-weight: 600;">用户名/邮箱</label>
  7371. <input type="text" id="loginUsername" required style="
  7372. width: 100%;
  7373. padding: 12px;
  7374. border: 2px solid #ddd;
  7375. border-radius: 8px;
  7376. font-size: 16px;
  7377. box-sizing: border-box;
  7378. ">
  7379. </div>
  7380. <div style="margin-bottom: 20px;">
  7381. <label style="display: block; margin-bottom: 5px; font-weight: 600;">密码</label>
  7382. <input type="password" id="loginPassword" required style="
  7383. width: 100%;
  7384. padding: 12px;
  7385. border: 2px solid #ddd;
  7386. border-radius: 8px;
  7387. font-size: 16px;
  7388. box-sizing: border-box;
  7389. ">
  7390. </div>
  7391. <div style="display: flex; gap: 10px;">
  7392. <button type="submit" style="
  7393. flex: 1;
  7394. padding: 12px;
  7395. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  7396. color: white;
  7397. border: none;
  7398. border-radius: 8px;
  7399. font-size: 16px;
  7400. cursor: pointer;
  7401. ">登录</button>
  7402. <button type="button" onclick="showRegisterForm()" style="
  7403. flex: 1;
  7404. padding: 12px;
  7405. background: #f0f0f0;
  7406. color: #333;
  7407. border: none;
  7408. border-radius: 8px;
  7409. font-size: 16px;
  7410. cursor: pointer;
  7411. ">注册</button>
  7412. </div>
  7413. <button type="button" onclick="closeLoginModal()" style="
  7414. width: 100%;
  7415. margin-top: 10px;
  7416. padding: 8px;
  7417. background: transparent;
  7418. color: #666;
  7419. border: 1px solid #ddd;
  7420. border-radius: 8px;
  7421. cursor: pointer;
  7422. ">取消</button>
  7423. </form>
  7424. </div>
  7425. </div>
  7426. `;
  7427. document.body.insertAdjacentHTML('beforeend', loginHtml);
  7428. }
  7429. function showRegisterForm() {
  7430. // 如果是从登录表单切换过来的,删除登录模态框
  7431. const loginModal = document.getElementById('loginModal');
  7432. if (loginModal) {
  7433. loginModal.remove();
  7434. } else {
  7435. // 如果是从欢迎页面直接过来的,隐藏欢迎页面
  7436. document.getElementById('auth-screen').style.display = 'none';
  7437. }
  7438. const registerHtml = `
  7439. <div id="registerModal" style="
  7440. position: fixed;
  7441. top: 0; left: 0;
  7442. width: 100%; height: 100%;
  7443. background: rgba(0,0,0,0.8);
  7444. display: flex;
  7445. justify-content: center;
  7446. align-items: center;
  7447. z-index: 10000;
  7448. ">
  7449. <div style="
  7450. background: white;
  7451. padding: 30px;
  7452. border-radius: 15px;
  7453. width: 90%;
  7454. max-width: 400px;
  7455. box-shadow: 0 20px 60px rgba(0,0,0,0.3);
  7456. ">
  7457. <h2 style="text-align: center; margin-bottom: 20px; color: #333;">注册账户</h2>
  7458. <form id="registerForm" onsubmit="handleRegister(event)">
  7459. <div style="margin-bottom: 15px;">
  7460. <label style="display: block; margin-bottom: 5px; font-weight: 600;">用户名</label>
  7461. <input type="text" id="registerUsername" required style="
  7462. width: 100%;
  7463. padding: 12px;
  7464. border: 2px solid #ddd;
  7465. border-radius: 8px;
  7466. font-size: 16px;
  7467. box-sizing: border-box;
  7468. ">
  7469. </div>
  7470. <div style="margin-bottom: 15px;">
  7471. <label style="display: block; margin-bottom: 5px; font-weight: 600;">邮箱</label>
  7472. <input type="email" id="registerEmail" required style="
  7473. width: 100%;
  7474. padding: 12px;
  7475. border: 2px solid #ddd;
  7476. border-radius: 8px;
  7477. font-size: 16px;
  7478. box-sizing: border-box;
  7479. ">
  7480. </div>
  7481. <div style="margin-bottom: 20px;">
  7482. <label style="display: block; margin-bottom: 5px; font-weight: 600;">密码</label>
  7483. <input type="password" id="registerPassword" required style="
  7484. width: 100%;
  7485. padding: 12px;
  7486. border: 2px solid #ddd;
  7487. border-radius: 8px;
  7488. font-size: 16px;
  7489. box-sizing: border-box;
  7490. ">
  7491. </div>
  7492. <div style="display: flex; gap: 10px;">
  7493. <button type="submit" style="
  7494. flex: 1;
  7495. padding: 12px;
  7496. background: linear-gradient(45deg, #4ecdc4, #44a08d);
  7497. color: white;
  7498. border: none;
  7499. border-radius: 8px;
  7500. font-size: 16px;
  7501. cursor: pointer;
  7502. ">注册</button>
  7503. <button type="button" onclick="showLoginFromRegister()" style="
  7504. flex: 1;
  7505. padding: 12px;
  7506. background: #f0f0f0;
  7507. color: #333;
  7508. border: none;
  7509. border-radius: 8px;
  7510. font-size: 16px;
  7511. cursor: pointer;
  7512. ">登录</button>
  7513. </div>
  7514. <button type="button" onclick="closeRegisterModal()" style="
  7515. width: 100%;
  7516. margin-top: 10px;
  7517. padding: 8px;
  7518. background: transparent;
  7519. color: #666;
  7520. border: 1px solid #ddd;
  7521. border-radius: 8px;
  7522. cursor: pointer;
  7523. ">取消</button>
  7524. </form>
  7525. </div>
  7526. </div>
  7527. `;
  7528. document.body.insertAdjacentHTML('beforeend', registerHtml);
  7529. }
  7530. function showLoginFromRegister() {
  7531. document.getElementById('registerModal').remove();
  7532. showLoginForm();
  7533. }
  7534. async function handleLogin(event) {
  7535. event.preventDefault();
  7536. const username = document.getElementById('loginUsername').value;
  7537. const password = document.getElementById('loginPassword').value;
  7538. try {
  7539. const result = await AuthService.login({ username, password });
  7540. closeLoginModal();
  7541. // 登录成功后刷新相关UI
  7542. updateUserStatusUI();
  7543. } catch (error) {
  7544. // 错误信息已经在AuthService.login中显示
  7545. }
  7546. }
  7547. async function handleRegister(event) {
  7548. event.preventDefault();
  7549. const username = document.getElementById('registerUsername').value;
  7550. const email = document.getElementById('registerEmail').value;
  7551. const password = document.getElementById('registerPassword').value;
  7552. try {
  7553. const result = await AuthService.register({ username, email, password });
  7554. closeRegisterModal();
  7555. // 注册成功后刷新相关UI
  7556. updateUserStatusUI();
  7557. } catch (error) {
  7558. // 错误信息已经在AuthService.register中显示
  7559. }
  7560. }
  7561. function closeLoginModal() {
  7562. const modal = document.getElementById('loginModal');
  7563. if (modal) {
  7564. modal.remove();
  7565. // 如果用户未登录,显示欢迎页面
  7566. if (!authManager.isAuthenticated()) {
  7567. showAuthScreen();
  7568. }
  7569. }
  7570. }
  7571. function closeRegisterModal() {
  7572. const modal = document.getElementById('registerModal');
  7573. if (modal) {
  7574. modal.remove();
  7575. // 如果用户未登录,显示欢迎页面
  7576. if (!authManager.isAuthenticated()) {
  7577. showAuthScreen();
  7578. }
  7579. }
  7580. }
  7581. // 更新用户状态UI
  7582. function updateUserStatusUI() {
  7583. // 这里可以添加更新用户状态相关的UI逻辑
  7584. // 比如显示用户头像、用户名等
  7585. if (authManager.isAuthenticated()) {
  7586. console.log('用户已登录:', authManager.user);
  7587. // 登录成功后显示主应用
  7588. showMainApp();
  7589. }
  7590. }
  7591. // 头像更换功能
  7592. function changeAvatar() {
  7593. const avatarOptions = [
  7594. "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'><circle cx='30' cy='30' r='30' fill='%23ff6b6b'/><circle cx='30' cy='22' r='8' fill='white'/><ellipse cx='30' cy='45' rx='15' ry='10' fill='white'/></svg>",
  7595. "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'><circle cx='30' cy='30' r='30' fill='%2364b5f6'/><circle cx='30' cy='22' r='8' fill='white'/><ellipse cx='30' cy='45' rx='15' ry='10' fill='white'/></svg>",
  7596. "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'><circle cx='30' cy='30' r='30' fill='%2381c784'/><circle cx='30' cy='22' r='8' fill='white'/><ellipse cx='30' cy='45' rx='15' ry='10' fill='white'/></svg>",
  7597. "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'><circle cx='30' cy='30' r='30' fill='%23ffb74d'/><circle cx='30' cy='22' r='8' fill='white'/><ellipse cx='30' cy='45' rx='15' ry='10' fill='white'/></svg>"
  7598. ];
  7599. const currentAvatar = document.getElementById('userAvatar').src;
  7600. let currentIndex = avatarOptions.indexOf(currentAvatar);
  7601. const nextIndex = (currentIndex + 1) % avatarOptions.length;
  7602. document.getElementById('userAvatar').src = avatarOptions[nextIndex];
  7603. showNotification('头像已更新', '您的头像已成功更换!');
  7604. }
  7605. // 修改密码功能
  7606. function changePassword() {
  7607. showNotification('修改密码', '密码修改功能将在后续版本中提供');
  7608. }
  7609. // 绑定手机号功能
  7610. function bindPhone() {
  7611. showNotification('手机号绑定', '手机号绑定功能将在后续版本中提供');
  7612. }
  7613. // 绑定邮箱功能
  7614. function bindEmail() {
  7615. showNotification('邮箱绑定', '邮箱绑定功能将在后续版本中提供');
  7616. }
  7617. // 关于应用功能
  7618. function showAbout() {
  7619. showNotification('关于应用', 'FashionCraft v1.0.0 - 专业的服装DIY设计平台');
  7620. }
  7621. // 清除缓存功能
  7622. function clearCache() {
  7623. if (confirm('确定要清除缓存吗?这将删除临时文件和设计草稿。')) {
  7624. showNotification('缓存已清除', '成功清除 23.5MB 缓存数据');
  7625. // 更新缓存大小显示
  7626. document.querySelector('.cache-size').textContent = '0MB';
  7627. setTimeout(() => {
  7628. document.querySelector('.cache-size').textContent = '1.2MB';
  7629. }, 2000);
  7630. }
  7631. }
  7632. // 意见反馈功能
  7633. function feedback() {
  7634. showNotification('意见反馈', '感谢您的反馈!我们会认真对待每一条建议');
  7635. }
  7636. // 保存设置功能
  7637. async function saveSettings() {
  7638. const userName = document.getElementById('userName').value;
  7639. const userBio = document.getElementById('userBio').value;
  7640. const userLocation = document.getElementById('userLocation').value;
  7641. if (!userName.trim()) {
  7642. showNotification('保存失败', '用户名不能为空');
  7643. return;
  7644. }
  7645. try {
  7646. const profileData = {
  7647. nickname: userName,
  7648. bio: userBio,
  7649. location: userLocation
  7650. };
  7651. const response = await UserAPI.updateProfile(profileData);
  7652. if (response.code === 200) {
  7653. // 更新本地用户信息
  7654. authManager.user = { ...authManager.user, ...response.data };
  7655. localStorage.setItem('fashioncraft_user', JSON.stringify(authManager.user));
  7656. showNotification('设置已保存', '您的个人设置已成功保存!');
  7657. }
  7658. } catch (error) {
  7659. showNotification('保存失败', error.message || '保存设置时出现错误');
  7660. console.error('保存设置失败:', error);
  7661. }
  7662. }
  7663. // 退出登录确认
  7664. function confirmLogout() {
  7665. if (confirm('确定要退出登录吗?未保存的设计将会丢失。')) {
  7666. logout();
  7667. }
  7668. }
  7669. // 退出登录功能
  7670. async function logout() {
  7671. try {
  7672. await AuthService.logout();
  7673. // 关闭设置模态框
  7674. closeSettingsModal();
  7675. // 返回到登录页面
  7676. showAuthScreen();
  7677. // 清除相关的全局状态
  7678. currentBodyPart = 'overall';
  7679. partColors = {
  7680. 'overall': '#ff6b6b',
  7681. 'left-sleeve': '#ff6b6b',
  7682. 'right-sleeve': '#ff6b6b',
  7683. 'hood': '#ff6b6b',
  7684. 'body': '#ff6b6b'
  7685. };
  7686. colorHistory = [];
  7687. aiChatHistory = [];
  7688. } catch (error) {
  7689. console.error('退出登录失败:', error);
  7690. showNotification('退出失败', '退出登录时出现错误,请稍后再试');
  7691. }
  7692. }
  7693. // 上传功能相关变量
  7694. let currentUploadStep = 1;
  7695. let selectedWorkType = '';
  7696. let uploadedFiles = [];
  7697. let selectedTags = [];
  7698. let selectedDesigns = [];
  7699. // 打开上传模态框
  7700. function openUploadModal() {
  7701. document.getElementById('uploadModal').style.display = 'flex';
  7702. resetUploadModal();
  7703. }
  7704. // 关闭上传模态框
  7705. function closeUploadModal() {
  7706. document.getElementById('uploadModal').style.display = 'none';
  7707. }
  7708. // 重置上传模态框
  7709. function resetUploadModal() {
  7710. currentUploadStep = 1;
  7711. selectedWorkType = '';
  7712. uploadedFiles = [];
  7713. selectedTags = [];
  7714. selectedDesigns = [];
  7715. updateUploadStep();
  7716. clearFormData();
  7717. }
  7718. // 更新上传步骤
  7719. function updateUploadStep() {
  7720. // 更新步骤指示器
  7721. document.querySelectorAll('.step').forEach((step, index) => {
  7722. if (index + 1 <= currentUploadStep) {
  7723. step.classList.add('active');
  7724. } else {
  7725. step.classList.remove('active');
  7726. }
  7727. });
  7728. // 显示对应步骤内容
  7729. document.querySelectorAll('.upload-step').forEach((step, index) => {
  7730. if (index + 1 === currentUploadStep) {
  7731. step.classList.add('active');
  7732. } else {
  7733. step.classList.remove('active');
  7734. }
  7735. });
  7736. // 更新按钮状态
  7737. const prevBtn = document.getElementById('prevBtn');
  7738. const nextBtn = document.getElementById('nextBtn');
  7739. const publishBtn = document.getElementById('publishBtn');
  7740. prevBtn.style.display = currentUploadStep > 1 ? 'block' : 'none';
  7741. if (currentUploadStep < 4) {
  7742. nextBtn.style.display = 'block';
  7743. publishBtn.style.display = 'none';
  7744. } else {
  7745. nextBtn.style.display = 'none';
  7746. publishBtn.style.display = 'block';
  7747. }
  7748. }
  7749. // 下一步(社区上传流程)
  7750. function nextUploadStep() {
  7751. if (validateCurrentStep()) {
  7752. currentUploadStep++;
  7753. updateUploadStep();
  7754. }
  7755. }
  7756. // 上一步
  7757. function prevStep() {
  7758. currentUploadStep--;
  7759. updateUploadStep();
  7760. }
  7761. // 验证当前步骤
  7762. function validateCurrentStep() {
  7763. switch (currentUploadStep) {
  7764. case 1:
  7765. if (!selectedWorkType) {
  7766. showNotification('请选择作品类型');
  7767. return false;
  7768. }
  7769. break;
  7770. case 2:
  7771. if (uploadedFiles.length === 0 && selectedDesigns.length === 0) {
  7772. showNotification('请上传内容或选择设计');
  7773. return false;
  7774. }
  7775. break;
  7776. case 3:
  7777. const title = document.getElementById('workTitle').value.trim();
  7778. if (!title) {
  7779. showNotification('请输入作品标题');
  7780. return false;
  7781. }
  7782. break;
  7783. case 4:
  7784. const copyrightAgree = document.getElementById('copyrightAgree').checked;
  7785. if (!copyrightAgree) {
  7786. showNotification('请同意版权声明');
  7787. return false;
  7788. }
  7789. break;
  7790. }
  7791. return true;
  7792. }
  7793. // 选择作品类型
  7794. function selectWorkType(type) {
  7795. selectedWorkType = type;
  7796. document.querySelectorAll('.work-type').forEach(item => {
  7797. item.classList.remove('selected');
  7798. });
  7799. document.querySelector(`[data-type="${type}"]`).classList.add('selected');
  7800. }
  7801. // 触发文件上传
  7802. function triggerFileUpload() {
  7803. document.getElementById('fileInput').click();
  7804. }
  7805. // 触发3D文件上传
  7806. function trigger3DUpload() {
  7807. document.getElementById('file3DInput').click();
  7808. }
  7809. // 处理文件上传
  7810. async function handleFileUpload(event) {
  7811. const files = Array.from(event.target.files);
  7812. for (const file of files) {
  7813. if (uploadedFiles.length >= 9) {
  7814. showNotification('上传限制', '最多只能上传9个文件');
  7815. break;
  7816. }
  7817. try {
  7818. // 先上传到服务器
  7819. const uploadResult = await UploadService.uploadImage(file, 'design');
  7820. // 将上传结果添加到文件列表
  7821. const fileData = {
  7822. file: file,
  7823. uploadResult: uploadResult,
  7824. url: uploadResult.file_url
  7825. };
  7826. uploadedFiles.push(fileData);
  7827. addFilePreview(file, uploadResult);
  7828. } catch (error) {
  7829. // 如果上传失败,仍然添加到本地列表(稍后重试)
  7830. uploadedFiles.push({ file: file, uploadResult: null });
  7831. addFilePreview(file);
  7832. console.warn('文件上传失败,将在发布时重试:', file.name, error);
  7833. }
  7834. }
  7835. }
  7836. // 处理3D文件上传
  7837. function handle3DUpload(event) {
  7838. const file = event.target.files[0];
  7839. if (file) {
  7840. showNotification('3D文件上传成功: ' + file.name);
  7841. }
  7842. }
  7843. // 添加文件预览
  7844. function addFilePreview(file) {
  7845. const preview = document.getElementById('uploadPreview');
  7846. const previewItem = document.createElement('div');
  7847. previewItem.className = 'preview-item';
  7848. if (file.type.startsWith('image/')) {
  7849. const img = document.createElement('img');
  7850. img.src = URL.createObjectURL(file);
  7851. previewItem.appendChild(img);
  7852. } else {
  7853. previewItem.innerHTML = '<div style="display: flex; align-items: center; justify-content: center; height: 100%; font-size: 24px;">🎬</div>';
  7854. }
  7855. const removeBtn = document.createElement('button');
  7856. removeBtn.className = 'preview-remove';
  7857. removeBtn.innerHTML = '×';
  7858. removeBtn.onclick = () => removeFilePreview(file, previewItem);
  7859. previewItem.appendChild(removeBtn);
  7860. preview.appendChild(previewItem);
  7861. }
  7862. // 移除文件预览
  7863. function removeFilePreview(file, previewItem) {
  7864. const index = uploadedFiles.indexOf(file);
  7865. if (index > -1) {
  7866. uploadedFiles.splice(index, 1);
  7867. }
  7868. previewItem.remove();
  7869. }
  7870. // 从我的设计选择
  7871. function selectFromMyDesigns(designId) {
  7872. const designItem = document.querySelector(`[onclick="selectFromMyDesigns(${designId})"]`);
  7873. if (selectedDesigns.includes(designId)) {
  7874. selectedDesigns = selectedDesigns.filter(id => id !== designId);
  7875. designItem.classList.remove('selected');
  7876. } else {
  7877. selectedDesigns.push(designId);
  7878. designItem.classList.add('selected');
  7879. }
  7880. }
  7881. // 切换标签
  7882. function toggleTag(tagElement) {
  7883. const tagText = tagElement.textContent;
  7884. if (selectedTags.includes(tagText)) {
  7885. selectedTags = selectedTags.filter(tag => tag !== tagText);
  7886. tagElement.classList.remove('selected');
  7887. } else {
  7888. selectedTags.push(tagText);
  7889. tagElement.classList.add('selected');
  7890. }
  7891. }
  7892. // 添加自定义标签
  7893. function addCustomTag(event) {
  7894. if (event.key === 'Enter') {
  7895. const input = event.target;
  7896. const tagText = '#' + input.value.trim();
  7897. if (tagText.length > 1 && !selectedTags.includes(tagText)) {
  7898. selectedTags.push(tagText);
  7899. const tagElement = document.createElement('span');
  7900. tagElement.className = 'tag selected';
  7901. tagElement.textContent = tagText;
  7902. tagElement.onclick = () => toggleTag(tagElement);
  7903. document.querySelector('.popular-tags').appendChild(tagElement);
  7904. input.value = '';
  7905. }
  7906. }
  7907. }
  7908. // 发布作品
  7909. async function publishWork() {
  7910. if (!validateCurrentStep()) {
  7911. return;
  7912. }
  7913. try {
  7914. // 验证必填字段
  7915. const titleElement = document.getElementById('workTitle');
  7916. const descElement = document.getElementById('workDescription');
  7917. if (!titleElement || !titleElement.value.trim()) {
  7918. showNotification('发布失败', '请输入作品标题');
  7919. return;
  7920. }
  7921. if (!selectedWorkType) {
  7922. showNotification('发布失败', '请选择作品类型');
  7923. return;
  7924. }
  7925. // 获取表单值并提供默认值
  7926. const visibilityElement = document.querySelector('input[name="visibility"]:checked');
  7927. const downloadElement = document.querySelector('input[name="download"]:checked');
  7928. // 映射前端工作类型到后端期望的格式
  7929. const workTypeMapping = {
  7930. 'design': 'design',
  7931. 'photo': 'fitting', // 照片试衣功能
  7932. 'video': 'tutorial', // 视频教程
  7933. '3d': 'design' // 3D设计也归类为设计
  7934. };
  7935. const mappedWorkType = workTypeMapping[selectedWorkType] || 'design';
  7936. // 准备发布数据
  7937. const workData = {
  7938. work_type: mappedWorkType,
  7939. title: titleElement.value.trim(),
  7940. description: descElement ? descElement.value.trim() : '',
  7941. tags: selectedTags || [],
  7942. visibility: visibilityElement ? visibilityElement.value : 'public',
  7943. allow_download: downloadElement ? downloadElement.value === 'allow' : true,
  7944. allow_comments: true
  7945. };
  7946. // 处理上传的文件
  7947. const imageUrls = [];
  7948. for (const fileData of uploadedFiles) {
  7949. if (fileData.uploadResult) {
  7950. // 文件已上传
  7951. imageUrls.push(fileData.uploadResult.file_url);
  7952. } else {
  7953. // 文件未上传,现在上传
  7954. try {
  7955. const uploadResult = await UploadService.uploadImage(fileData.file, 'community');
  7956. imageUrls.push(uploadResult.file_url);
  7957. } catch (uploadError) {
  7958. console.warn('文件上传失败:', fileData.file.name, uploadError);
  7959. }
  7960. }
  7961. }
  7962. workData.images = imageUrls;
  7963. // 处理选中的设计
  7964. if (selectedDesigns.length > 0) {
  7965. // 假设只选择一个设计
  7966. workData.design_id = selectedDesigns[0];
  7967. }
  7968. // 记录发送的数据以便调试
  7969. console.log('发布作品数据:', workData);
  7970. // 调用发布API
  7971. const result = await CommunityAPI.publishWork(workData);
  7972. if (result.code === 200) {
  7973. showNotification('发布成功', '你的作品已成功发布到社区!');
  7974. closeUploadModal();
  7975. // 清空表单数据
  7976. clearFormData();
  7977. resetUploadModal();
  7978. // 可以跳转到社区页面查看刚发布的作品
  7979. setTimeout(() => {
  7980. switchPage('community');
  7981. updateNavigation('community');
  7982. }, 1500);
  7983. } else {
  7984. throw new Error(result.message || '发布失败');
  7985. }
  7986. } catch (error) {
  7987. console.error('发布作品失败:', error);
  7988. console.error('发送的数据:', workData);
  7989. let errorMessage = '发布作品时出现错误,请稍后再试';
  7990. // 根据错误类型提供更具体的提示
  7991. if (error.message) {
  7992. if (error.message.includes('500')) {
  7993. errorMessage = '服务器暂时无法处理请求,请稍后再试';
  7994. // 500错误时进行健康检查
  7995. checkServerHealth();
  7996. } else if (error.message.includes('400')) {
  7997. errorMessage = '提交的数据格式有误,请检查后重试';
  7998. } else if (error.message.includes('401')) {
  7999. errorMessage = '登录已过期,请重新登录';
  8000. } else if (error.message.includes('403')) {
  8001. errorMessage = '没有权限执行此操作';
  8002. } else {
  8003. errorMessage = error.message;
  8004. }
  8005. }
  8006. showNotification('发布失败', errorMessage);
  8007. }
  8008. }
  8009. // 服务器健康检查
  8010. async function checkServerHealth() {
  8011. try {
  8012. console.log('开始检查服务器健康状态...');
  8013. const response = await fetch(`${API_CONFIG.baseURL}/health`, {
  8014. method: 'GET',
  8015. timeout: 5000
  8016. });
  8017. if (response.ok) {
  8018. console.log('服务器健康检查:正常');
  8019. setTimeout(() => {
  8020. showNotification('服务器状态', '服务器连接正常,但社区功能暂时不可用');
  8021. }, 2000);
  8022. } else {
  8023. console.log('服务器健康检查:异常', response.status);
  8024. setTimeout(() => {
  8025. showNotification('服务器状态', '服务器响应异常,请稍后再试');
  8026. }, 2000);
  8027. }
  8028. } catch (error) {
  8029. console.log('服务器健康检查:连接失败', error);
  8030. setTimeout(() => {
  8031. showNotification('服务器状态', '服务器连接失败,请检查网络连接');
  8032. }, 2000);
  8033. }
  8034. }
  8035. // 清空表单数据
  8036. function clearFormData() {
  8037. document.getElementById('workTitle').value = '';
  8038. document.getElementById('workDescription').value = '';
  8039. document.getElementById('customTag').value = '';
  8040. document.getElementById('uploadPreview').innerHTML = '';
  8041. document.querySelectorAll('.work-type').forEach(item => item.classList.remove('selected'));
  8042. document.querySelectorAll('.design-item').forEach(item => item.classList.remove('selected'));
  8043. document.querySelectorAll('.tag').forEach(item => item.classList.remove('selected'));
  8044. }
  8045. // 字符计数
  8046. document.addEventListener('DOMContentLoaded', function() {
  8047. const titleInput = document.getElementById('workTitle');
  8048. const descInput = document.getElementById('workDescription');
  8049. const titleCount = document.getElementById('titleCount');
  8050. const descCount = document.getElementById('descCount');
  8051. if (titleInput && titleCount) {
  8052. titleInput.addEventListener('input', function() {
  8053. titleCount.textContent = this.value.length;
  8054. });
  8055. }
  8056. if (descInput && descCount) {
  8057. descInput.addEventListener('input', function() {
  8058. descCount.textContent = this.value.length;
  8059. });
  8060. }
  8061. });
  8062. // 草稿箱功能
  8063. function showDrafts() {
  8064. document.getElementById('draftsModal').style.display = 'flex';
  8065. }
  8066. function closeDraftsModal() {
  8067. document.getElementById('draftsModal').style.display = 'none';
  8068. }
  8069. function editDraft(draftId) {
  8070. showNotification('编辑草稿: ' + draftId);
  8071. closeDraftsModal();
  8072. openUploadModal();
  8073. }
  8074. function deleteDraft(draftId) {
  8075. if (confirm('确定要删除这个草稿吗?')) {
  8076. showNotification('草稿已删除');
  8077. }
  8078. }
  8079. // 我的作品功能
  8080. function showMyWorks() {
  8081. document.getElementById('myWorksModal').style.display = 'flex';
  8082. }
  8083. function closeMyWorksModal() {
  8084. document.getElementById('myWorksModal').style.display = 'none';
  8085. }
  8086. function switchWorksTab(tab) {
  8087. document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
  8088. event.target.classList.add('active');
  8089. if (tab === 'published') {
  8090. document.getElementById('publishedWorks').style.display = 'block';
  8091. document.getElementById('analyticsWorks').style.display = 'none';
  8092. } else {
  8093. document.getElementById('publishedWorks').style.display = 'none';
  8094. document.getElementById('analyticsWorks').style.display = 'block';
  8095. }
  8096. }
  8097. function editWork(workId) {
  8098. showNotification('编辑作品: ' + workId);
  8099. closeMyWorksModal();
  8100. }
  8101. function deleteWork(workId) {
  8102. if (confirm('确定要删除这个作品吗?')) {
  8103. showNotification('作品已删除');
  8104. }
  8105. }
  8106. // 通知系统
  8107. function showNotification(title, message) {
  8108. // 创建通知元素
  8109. const notification = document.createElement('div');
  8110. notification.style.cssText = `
  8111. position: fixed;
  8112. top: 20px;
  8113. left: 50%;
  8114. transform: translateX(-50%);
  8115. background: linear-gradient(45deg, #ff6b6b, #ffa726);
  8116. color: white;
  8117. padding: 15px 20px;
  8118. border-radius: 25px;
  8119. box-shadow: 0 10px 30px rgba(0,0,0,0.3);
  8120. z-index: 10000;
  8121. max-width: 300px;
  8122. text-align: center;
  8123. animation: slideDown 0.3s ease;
  8124. `;
  8125. notification.innerHTML = `
  8126. <div style="font-weight: 600; margin-bottom: 5px;">${title}</div>
  8127. <div style="font-size: 14px; opacity: 0.9;">${message}</div>
  8128. `;
  8129. // 添加滑入动画
  8130. const style = document.createElement('style');
  8131. style.textContent = `
  8132. @keyframes slideDown {
  8133. from { transform: translateX(-50%) translateY(-100%); opacity: 0; }
  8134. to { transform: translateX(-50%) translateY(0); opacity: 1; }
  8135. }
  8136. `;
  8137. document.head.appendChild(style);
  8138. document.body.appendChild(notification);
  8139. // 3秒后自动移除
  8140. setTimeout(() => {
  8141. notification.style.animation = 'slideDown 0.3s ease reverse';
  8142. setTimeout(() => {
  8143. document.body.removeChild(notification);
  8144. }, 300);
  8145. }, 3000);
  8146. }
  8147. // 触摸手势支持
  8148. let startX, startY;
  8149. document.addEventListener('touchstart', function(e) {
  8150. startX = e.touches[0].clientX;
  8151. startY = e.touches[0].clientY;
  8152. });
  8153. document.addEventListener('touchend', function(e) {
  8154. if (!startX || !startY) return;
  8155. let endX = e.changedTouches[0].clientX;
  8156. let endY = e.changedTouches[0].clientY;
  8157. let diffX = startX - endX;
  8158. let diffY = startY - endY;
  8159. // 横向滑动切换轮播图
  8160. if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 50) {
  8161. if (diffX > 0) {
  8162. nextSlide();
  8163. } else {
  8164. currentSlide = currentSlide > 0 ? currentSlide - 1 : 2;
  8165. updateSlider();
  8166. }
  8167. }
  8168. startX = startY = null;
  8169. });
  8170. // 页面可见性API - 当页面不可见时暂停动画
  8171. document.addEventListener('visibilitychange', function() {
  8172. if (document.hidden) {
  8173. clearInterval(slideInterval);
  8174. } else {
  8175. slideInterval = setInterval(nextSlide, 4000);
  8176. }
  8177. });
  8178. // 防止点击穿透
  8179. document.addEventListener('click', function(e) {
  8180. if (e.target.closest('.modal')) {
  8181. e.stopPropagation();
  8182. }
  8183. });
  8184. // 模态框外部点击关闭
  8185. document.getElementById('modal').addEventListener('click', function(e) {
  8186. if (e.target === this) {
  8187. closeModal();
  8188. }
  8189. });
  8190. // 设置模态框外部点击关闭
  8191. document.getElementById('settingsModal').addEventListener('click', function(e) {
  8192. if (e.target === this) {
  8193. closeSettingsModal();
  8194. }
  8195. });
  8196. // 初始化服装设计器
  8197. function initializeClothingDesigner() {
  8198. // 设置默认宝蓝色
  8199. selectClothingColor('宝蓝色');
  8200. // 设置默认选中整体
  8201. selectBodyPart('overall');
  8202. console.log('服装设计器已初始化,已加载', availableColors.length, '种颜色');
  8203. }
  8204. // 页面加载完成后初始化设计器
  8205. window.addEventListener('load', function() {
  8206. setTimeout(initializeClothingDesigner, 500);
  8207. });
  8208. // ============ 3D试衣间功能函数 ============
  8209. // 流程控制
  8210. let currentFittingStep = 'upload';
  8211. let selectedClothing = null;
  8212. let userPhoto = null;
  8213. function nextStep(stepName) {
  8214. // 检查参数是否有效
  8215. if (!stepName) {
  8216. console.error('nextStep: stepName is required');
  8217. return;
  8218. }
  8219. // 检查当前步骤元素是否存在
  8220. const currentStepElement = document.getElementById(`${currentFittingStep}-step`);
  8221. if (currentStepElement) {
  8222. currentStepElement.style.display = 'none';
  8223. }
  8224. // 检查目标步骤元素是否存在
  8225. const targetStepElement = document.getElementById(`${stepName}-step`);
  8226. if (targetStepElement) {
  8227. targetStepElement.style.display = 'block';
  8228. }
  8229. // 更新流程导航状态
  8230. updateStepNavigation(stepName);
  8231. currentFittingStep = stepName;
  8232. showNotification('流程进度', `已进入${getStepTitle(stepName)}阶段`);
  8233. }
  8234. function previousStep(stepName) {
  8235. // 检查参数是否有效
  8236. if (!stepName) {
  8237. console.error('previousStep: stepName is required');
  8238. return;
  8239. }
  8240. // 检查当前步骤元素是否存在
  8241. const currentStepElement = document.getElementById(`${currentFittingStep}-step`);
  8242. if (currentStepElement) {
  8243. currentStepElement.style.display = 'none';
  8244. }
  8245. // 检查目标步骤元素是否存在
  8246. const targetStepElement = document.getElementById(`${stepName}-step`);
  8247. if (targetStepElement) {
  8248. targetStepElement.style.display = 'block';
  8249. }
  8250. // 更新流程导航状态
  8251. updateStepNavigation(stepName);
  8252. currentFittingStep = stepName;
  8253. }
  8254. function updateStepNavigation(activeStep) {
  8255. document.querySelectorAll('.flow-step').forEach(step => {
  8256. step.classList.remove('active');
  8257. if (step.getAttribute('data-step') === activeStep) {
  8258. step.classList.add('active');
  8259. }
  8260. });
  8261. }
  8262. function getStepTitle(stepName) {
  8263. const titles = {
  8264. 'upload': '照片上传',
  8265. 'clothing': '服装选择',
  8266. 'fitting': '试衣展示'
  8267. };
  8268. return titles[stepName] || stepName;
  8269. }
  8270. // ============ 照片上传功能 ============
  8271. function selectUploadMethod(method) {
  8272. // 更新选择状态
  8273. document.querySelectorAll('.upload-method').forEach(m => m.classList.remove('active'));
  8274. document.querySelector(`[data-method="${method}"]`).classList.add('active');
  8275. // 显示对应界面
  8276. if (method === 'camera') {
  8277. document.getElementById('camera-mode').style.display = 'block';
  8278. document.getElementById('gallery-mode').style.display = 'none';
  8279. } else {
  8280. document.getElementById('camera-mode').style.display = 'none';
  8281. document.getElementById('gallery-mode').style.display = 'block';
  8282. }
  8283. showNotification('上传方式', `已选择${method === 'camera' ? '拍照模式' : '相册选择'}`);
  8284. }
  8285. function startCamera() {
  8286. showNotification('启动摄像头', '正在访问摄像头权限...');
  8287. // 模拟摄像头启动
  8288. setTimeout(() => {
  8289. document.querySelector('.camera-placeholder').innerHTML = `
  8290. <div class="camera-icon">📹</div>
  8291. <div class="camera-text">摄像头已启动</div>
  8292. <div class="camera-hint">请对准镜头保持正面站立</div>
  8293. `;
  8294. showNotification('摄像头就绪', '可以开始拍摄了!');
  8295. }, 1500);
  8296. }
  8297. function capturePhoto() {
  8298. showNotification('拍摄照片', '正在拍摄...');
  8299. // 模拟拍照效果
  8300. setTimeout(() => {
  8301. document.getElementById('pose-calibration').style.display = 'block';
  8302. simulatePoseDetection();
  8303. showNotification('拍摄成功', '正在进行姿势校准...');
  8304. }, 1000);
  8305. }
  8306. function switchCamera() {
  8307. showNotification('切换摄像头', '已切换到前置/后置摄像头');
  8308. }
  8309. function handlePhotoUpload(input) {
  8310. const file = input.files[0];
  8311. if (file) {
  8312. const reader = new FileReader();
  8313. reader.onload = function(e) {
  8314. userPhoto = e.target.result;
  8315. document.getElementById('crop-area').style.display = 'block';
  8316. showNotification('照片上传', '请调整裁剪区域');
  8317. };
  8318. reader.readAsDataURL(file);
  8319. }
  8320. }
  8321. function resetCrop() {
  8322. showNotification('重置裁剪', '已重置到原始尺寸');
  8323. }
  8324. function confirmCrop() {
  8325. document.getElementById('pose-calibration').style.display = 'block';
  8326. simulatePoseDetection();
  8327. showNotification('裁剪完成', '正在进行姿势校准...');
  8328. }
  8329. function simulatePoseDetection() {
  8330. const statuses = document.querySelectorAll('.status-item');
  8331. let currentIndex = 2; // 从身形分析开始
  8332. const updateStatus = () => {
  8333. if (currentIndex < statuses.length) {
  8334. const item = statuses[currentIndex];
  8335. const icon = item.querySelector('.status-icon');
  8336. icon.textContent = '✅';
  8337. currentIndex++;
  8338. if (currentIndex < statuses.length) {
  8339. setTimeout(updateStatus, 1000);
  8340. } else {
  8341. showNotification('校准完成', '人体姿势识别成功!');
  8342. }
  8343. }
  8344. };
  8345. setTimeout(updateStatus, 1000);
  8346. }
  8347. function recalibrate() {
  8348. // 重置状态
  8349. const statuses = document.querySelectorAll('.status-item');
  8350. statuses.forEach((item, index) => {
  8351. const icon = item.querySelector('.status-icon');
  8352. if (index >= 2) {
  8353. icon.textContent = '⏳';
  8354. }
  8355. });
  8356. simulatePoseDetection();
  8357. showNotification('重新校准', '正在重新分析姿势...');
  8358. }
  8359. // ============ 服装选择功能 ============
  8360. function switchClothingTab(tabName) {
  8361. // 更新标签状态
  8362. document.querySelectorAll('.clothing-tab').forEach(tab => tab.classList.remove('active'));
  8363. document.querySelector(`[data-tab="${tabName}"]`).classList.add('active');
  8364. // 显示对应内容
  8365. document.querySelectorAll('.clothing-content').forEach(content => {
  8366. content.style.display = 'none';
  8367. });
  8368. document.getElementById(`${tabName}-content`).style.display = 'block';
  8369. const tabNames = {
  8370. 'my-designs': '我的设计',
  8371. 'community': '社区热门',
  8372. 'brands': '品牌合作'
  8373. };
  8374. showNotification('切换分类', `已切换到${tabNames[tabName]}`);
  8375. }
  8376. function selectClothing(clothingId) {
  8377. selectedClothing = clothingId;
  8378. // 视觉反馈
  8379. document.querySelectorAll('.design-item, .trending-item, .brand-item').forEach(item => {
  8380. item.classList.remove('selected');
  8381. });
  8382. event.currentTarget.classList.add('selected');
  8383. showNotification('选择服装', '已选择该款设计,可以进行试穿了!');
  8384. }
  8385. // ============ 试衣展示功能 ============
  8386. let currentRotation = 0;
  8387. let currentLighting = 'natural';
  8388. let compareMode = 'split';
  8389. function rotateFitting(direction) {
  8390. if (direction === 'left') {
  8391. currentRotation -= 30;
  8392. } else if (direction === 'right') {
  8393. currentRotation += 30;
  8394. } else {
  8395. currentRotation = 0;
  8396. }
  8397. const viewport = document.querySelector('.fitting-viewport');
  8398. if (viewport) {
  8399. viewport.style.transform = `rotateY(${currentRotation}deg)`;
  8400. }
  8401. showNotification('旋转视角', `视角:${currentRotation}°`);
  8402. }
  8403. function setFittingLight(lightType) {
  8404. // 更新按钮状态
  8405. document.querySelectorAll('.lighting-btn').forEach(btn => btn.classList.remove('active'));
  8406. event.currentTarget.classList.add('active');
  8407. currentLighting = lightType;
  8408. const lightFilters = {
  8409. 'natural': 'brightness(1.1) contrast(1.05)',
  8410. 'indoor': 'brightness(0.9) sepia(0.1)',
  8411. 'studio': 'brightness(1.2) contrast(1.1) saturate(1.1)'
  8412. };
  8413. const viewport = document.querySelector('.fitting-viewport');
  8414. if (viewport) {
  8415. viewport.style.filter = lightFilters[lightType];
  8416. }
  8417. const lightNames = {
  8418. 'natural': '自然光',
  8419. 'indoor': '室内光',
  8420. 'studio': '摄影光'
  8421. };
  8422. showNotification('光照调节', `已切换到${lightNames[lightType]}`);
  8423. }
  8424. function toggleCompare(mode) {
  8425. // 更新按钮状态
  8426. document.querySelectorAll('.compare-btn').forEach(btn => btn.classList.remove('active'));
  8427. event.currentTarget.classList.add('active');
  8428. compareMode = mode;
  8429. const modeNames = {
  8430. 'split': '左右对比',
  8431. 'overlay': '叠加对比'
  8432. };
  8433. showNotification('对比模式', `已切换到${modeNames[mode]}`);
  8434. }
  8435. function retryFitting() {
  8436. showNotification('重新试穿', '正在重新进行智能贴合...');
  8437. // 模拟重新试穿过程
  8438. setTimeout(() => {
  8439. showNotification('试穿完成', '新的试穿效果已生成!');
  8440. }, 2000);
  8441. }
  8442. // ============ 输出功能 ============
  8443. function saveImageCard() {
  8444. showNotification('保存形象卡', '正在生成专属形象卡...');
  8445. setTimeout(() => {
  8446. showNotification('保存成功', '形象卡已保存到相册!');
  8447. }, 1500);
  8448. }
  8449. function shareToCommunity() {
  8450. showNotification('分享到社区', '正在上传到设计社区...');
  8451. setTimeout(() => {
  8452. showNotification('分享成功', '已分享到社区,快去看看大家的反应吧!');
  8453. }, 2000);
  8454. }
  8455. function buyNow() {
  8456. if (!selectedClothing) {
  8457. showNotification('购买提醒', '请先选择要购买的服装');
  8458. return;
  8459. }
  8460. showNotification('跳转购买', '正在跳转到购买页面...');
  8461. setTimeout(() => {
  8462. showNotification('购买页面', '已为您打开购买链接!');
  8463. }, 1000);
  8464. }
  8465. // ============ 试衣间初始化 ============
  8466. function initializeFittingRoom() {
  8467. // 设置默认状态
  8468. currentFittingStep = 'upload';
  8469. selectUploadMethod('camera');
  8470. switchClothingTab('my-designs');
  8471. console.log('3D试衣间已初始化');
  8472. }
  8473. // 页面加载时初始化试衣间
  8474. document.addEventListener('DOMContentLoaded', function() {
  8475. if (document.getElementById('ar-page')) {
  8476. initializeFittingRoom();
  8477. }
  8478. });
  8479. </script>
  8480. </body>
  8481. </html>