灵活用工项目

flexible-employment-demo.html 110KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379
  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, maximum-scale=1.0, user-scalable=no">
  6. <meta name="theme-color" content="#7C3AED">
  7. <title>灵活用工 - 智能用工助手</title>
  8. <link href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css" rel="stylesheet">
  9. <style>
  10. @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap');
  11. :root {
  12. --primary: #7C3AED;
  13. --primary-light: #A78BFA;
  14. --primary-dark: #5B21B6;
  15. --primary-bg: #F5F3FF;
  16. --primary-100: #EDE9FE;
  17. --secondary: #6366F1;
  18. --accent: #EC4899;
  19. --success: #10B981;
  20. --success-light: #D1FAE5;
  21. --warning: #F59E0B;
  22. --warning-light: #FEF3C7;
  23. --danger: #EF4444;
  24. --danger-light: #FEE2E2;
  25. --info: #3B82F6;
  26. --info-light: #DBEAFE;
  27. --bg: #FAF5FF;
  28. --surface: #FFFFFF;
  29. --foreground: #0F172A;
  30. --gray-50: #F9FAFB;
  31. --gray-100: #F3F4F6;
  32. --gray-200: #E5E7EB;
  33. --gray-300: #D1D5DB;
  34. --gray-400: #9CA3AF;
  35. --gray-500: #6B7280;
  36. --gray-600: #4B5563;
  37. --gray-700: #374151;
  38. --gray-800: #1F2937;
  39. --gray-900: #111827;
  40. --muted: #64748B;
  41. --muted-light: #94A3B8;
  42. --border: #E2E8F0;
  43. --border-light: #F1F5F9;
  44. --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
  45. --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.07), 0 2px 4px -2px rgba(0,0,0,0.05);
  46. --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.08), 0 4px 6px -4px rgba(0,0,0,0.05);
  47. --shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.1), 0 8px 10px -6px rgba(0,0,0,0.06);
  48. --radius-sm: 6px;
  49. --radius-md: 10px;
  50. --radius-lg: 14px;
  51. --radius-xl: 20px;
  52. --radius-full: 9999px;
  53. --safe-top: env(safe-area-inset-top, 0px);
  54. --safe-bottom: env(safe-area-inset-bottom, 0px);
  55. --nav-h: 56px;
  56. }
  57. * { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
  58. body {
  59. font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  60. background: var(--bg);
  61. color: var(--foreground);
  62. overflow: hidden;
  63. height: 100dvh;
  64. width: 100%;
  65. position: fixed;
  66. top: 0; left: 0;
  67. }
  68. /* ===== APP SHELL ===== */
  69. .app {
  70. position: relative;
  71. width: 100%;
  72. height: 100dvh;
  73. max-width: 480px;
  74. margin: 0 auto;
  75. background: var(--bg);
  76. overflow: hidden;
  77. }
  78. /* ===== PAGES ===== */
  79. .page {
  80. position: absolute;
  81. top: 0; left: 0; right: 0; bottom: 0;
  82. display: none;
  83. flex-direction: column;
  84. }
  85. .page.active { display: flex; }
  86. /* ===== LOGIN PAGE ===== */
  87. .login-page {
  88. background: var(--surface);
  89. padding: 0 24px;
  90. justify-content: center;
  91. overflow-y: auto;
  92. }
  93. .login-visual {
  94. background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
  95. border-radius: var(--radius-xl);
  96. padding: 32px 24px;
  97. color: white;
  98. margin-bottom: 32px;
  99. position: relative;
  100. overflow: hidden;
  101. }
  102. .login-visual::before {
  103. content: '';
  104. position: absolute;
  105. top: -50%; right: -50%;
  106. width: 100%; height: 100%;
  107. background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
  108. }
  109. .login-visual h1 {
  110. font-size: 24px;
  111. font-weight: 800;
  112. margin-bottom: 8px;
  113. position: relative;
  114. }
  115. .login-visual p {
  116. font-size: 15px;
  117. opacity: 0.9;
  118. position: relative;
  119. }
  120. .login-visual .features {
  121. margin-top: 20px;
  122. position: relative;
  123. }
  124. .login-visual .feature-item {
  125. display: flex;
  126. align-items: center;
  127. gap: 10px;
  128. margin-bottom: 10px;
  129. font-size: 14px;
  130. }
  131. .login-visual .feature-item i {
  132. color: var(--success);
  133. font-size: 18px;
  134. }
  135. .login-card h2 {
  136. font-size: 22px;
  137. font-weight: 700;
  138. margin-bottom: 6px;
  139. }
  140. .login-card .subtitle {
  141. color: var(--gray-500);
  142. margin-bottom: 24px;
  143. font-size: 14px;
  144. }
  145. .form-group {
  146. margin-bottom: 16px;
  147. }
  148. .form-label {
  149. display: block;
  150. font-weight: 600;
  151. font-size: 13px;
  152. color: var(--gray-700);
  153. margin-bottom: 6px;
  154. }
  155. .form-input {
  156. width: 100%;
  157. height: 48px;
  158. padding: 0 16px;
  159. border: 1px solid var(--gray-300);
  160. border-radius: var(--radius-md);
  161. font-size: 15px;
  162. font-family: inherit;
  163. transition: all 0.15s;
  164. background: var(--surface);
  165. color: var(--foreground);
  166. }
  167. .form-input:focus {
  168. outline: none;
  169. border-color: var(--primary);
  170. box-shadow: 0 0 0 3px var(--primary-100);
  171. }
  172. .form-input::placeholder { color: var(--gray-400); }
  173. .login-divider {
  174. display: flex;
  175. align-items: center;
  176. gap: 12px;
  177. margin: 20px 0;
  178. color: var(--gray-400);
  179. font-size: 13px;
  180. }
  181. .login-divider::before, .login-divider::after {
  182. content: ''; flex: 1; height: 1px; background: var(--gray-200);
  183. }
  184. .wechat-btn {
  185. width: 100%;
  186. height: 48px;
  187. background: #07C160;
  188. color: white;
  189. border-radius: var(--radius-md);
  190. font-size: 15px;
  191. font-weight: 600;
  192. display: flex;
  193. align-items: center;
  194. justify-content: center;
  195. gap: 8px;
  196. cursor: pointer;
  197. border: none;
  198. font-family: inherit;
  199. transition: background 0.15s;
  200. }
  201. .wechat-btn:active { background: #06AE56; }
  202. .btn {
  203. display: inline-flex;
  204. align-items: center;
  205. justify-content: center;
  206. gap: 8px;
  207. padding: 12px 20px;
  208. border-radius: var(--radius-md);
  209. font-weight: 600;
  210. font-size: 14px;
  211. cursor: pointer;
  212. transition: all 0.15s;
  213. border: none;
  214. font-family: inherit;
  215. }
  216. .btn:active { transform: scale(0.97); }
  217. .btn-primary { background: var(--primary); color: white; }
  218. .btn-primary:active { background: var(--primary-dark); }
  219. .btn-secondary { background: var(--surface); color: var(--gray-700); border: 1px solid var(--gray-300); }
  220. .btn-success { background: var(--success); color: white; }
  221. .btn-ghost { background: transparent; color: var(--gray-600); }
  222. .btn-lg { height: 48px; padding: 0 24px; font-size: 15px; }
  223. .btn-sm { height: 32px; padding: 0 12px; font-size: 12px; }
  224. .btn-full { width: 100%; }
  225. /* ===== CHAT PAGE ===== */
  226. .chat-page {
  227. flex-direction: column;
  228. }
  229. .chat-layout {
  230. display: flex;
  231. flex: 1;
  232. overflow: hidden;
  233. margin-top: calc(var(--nav-h) + var(--safe-top));
  234. }
  235. .chat-sidebar {
  236. width: 0;
  237. overflow: hidden;
  238. background: var(--gray-50);
  239. border-right: 1px solid var(--border-light);
  240. transition: width 0.3s cubic-bezier(0.32,0.72,0,1);
  241. display: flex;
  242. flex-direction: column;
  243. flex-shrink: 0;
  244. }
  245. .chat-sidebar.open {
  246. width: 240px;
  247. }
  248. .sidebar-header {
  249. padding: 14px 14px 10px;
  250. border-bottom: 1px solid var(--border-light);
  251. display: flex;
  252. align-items: center;
  253. justify-content: space-between;
  254. }
  255. .sidebar-header h3 {
  256. font-size: 15px;
  257. font-weight: 700;
  258. }
  259. .new-chat-btn {
  260. width: 32px; height: 32px;
  261. border-radius: var(--radius-sm);
  262. background: var(--primary);
  263. color: white;
  264. border: none;
  265. cursor: pointer;
  266. display: flex;
  267. align-items: center;
  268. justify-content: center;
  269. font-size: 16px;
  270. }
  271. .chat-list {
  272. flex: 1;
  273. overflow-y: auto;
  274. padding: 8px;
  275. }
  276. .chat-item {
  277. padding: 10px 12px;
  278. border-radius: var(--radius-sm);
  279. cursor: pointer;
  280. margin-bottom: 2px;
  281. transition: background 0.15s;
  282. }
  283. .chat-item:active { background: var(--gray-100); }
  284. .chat-item.active { background: var(--primary-bg); border: 1px solid var(--primary-100); }
  285. .chat-item-title { font-weight: 600; font-size: 13px; color: var(--gray-800); margin-bottom: 2px; }
  286. .chat-item-time { font-size: 11px; color: var(--gray-400); }
  287. .chat-main {
  288. flex: 1;
  289. display: flex;
  290. flex-direction: column;
  291. min-width: 0;
  292. overflow: hidden;
  293. padding-bottom: 68px;
  294. }
  295. /* ===== TOP NAV ===== */
  296. .top-nav {
  297. position: fixed;
  298. top: 0; left: 50%;
  299. transform: translateX(-50%);
  300. width: 100%; max-width: 480px;
  301. height: calc(var(--nav-h) + var(--safe-top));
  302. padding-top: var(--safe-top);
  303. background: rgba(255,255,255,0.88);
  304. backdrop-filter: blur(20px);
  305. -webkit-backdrop-filter: blur(20px);
  306. border-bottom: 1px solid var(--border-light);
  307. display: flex;
  308. align-items: center;
  309. justify-content: space-between;
  310. padding-left: 14px; padding-right: 14px;
  311. z-index: 100;
  312. }
  313. .top-nav-title {
  314. display: flex;
  315. align-items: center;
  316. gap: 8px;
  317. font-weight: 700;
  318. font-size: 17px;
  319. }
  320. .top-nav-title i { font-size: 22px; color: var(--primary); }
  321. .top-nav-actions { display: flex; align-items: center; gap: 2px; }
  322. .nav-btn {
  323. width: 40px; height: 40px;
  324. border-radius: var(--radius-full);
  325. border: none;
  326. background: transparent;
  327. display: flex;
  328. align-items: center;
  329. justify-content: center;
  330. cursor: pointer;
  331. position: relative;
  332. font-size: 20px;
  333. color: var(--gray-500);
  334. transition: background 0.15s;
  335. }
  336. .nav-btn:active { background: var(--primary-bg); }
  337. .nav-badge {
  338. position: absolute; top: 4px; right: 4px;
  339. min-width: 16px; height: 16px;
  340. background: var(--danger);
  341. color: white;
  342. font-size: 10px;
  343. font-weight: 700;
  344. border-radius: var(--radius-full);
  345. display: flex;
  346. align-items: center;
  347. justify-content: center;
  348. border: 2px solid white;
  349. padding: 0 3px;
  350. }
  351. .nav-avatar {
  352. width: 32px; height: 32px;
  353. border-radius: var(--radius-full);
  354. background: linear-gradient(135deg, var(--primary), var(--secondary));
  355. display: flex;
  356. align-items: center;
  357. justify-content: center;
  358. color: white;
  359. font-weight: 700;
  360. font-size: 13px;
  361. cursor: pointer;
  362. }
  363. /* ===== CHAT AREA ===== */
  364. .chat-area {
  365. flex: 1;
  366. overflow-y: auto;
  367. padding: 16px;
  368. scroll-behavior: smooth;
  369. -webkit-overflow-scrolling: touch;
  370. }
  371. .chat-msg {
  372. display: flex;
  373. gap: 10px;
  374. margin-bottom: 16px;
  375. animation: msgIn 0.35s cubic-bezier(0.34,1.56,0.64,1) both;
  376. }
  377. .chat-msg.user { flex-direction: row-reverse; }
  378. .chat-avatar {
  379. width: 34px; height: 34px;
  380. border-radius: var(--radius-full);
  381. flex-shrink: 0;
  382. display: flex;
  383. align-items: center;
  384. justify-content: center;
  385. font-size: 14px;
  386. }
  387. .chat-avatar.ai {
  388. background: linear-gradient(135deg, var(--primary), var(--secondary));
  389. color: white;
  390. }
  391. .chat-avatar.user {
  392. background: var(--primary-bg);
  393. color: var(--primary);
  394. font-weight: 700;
  395. }
  396. .chat-bubble {
  397. max-width: 80%;
  398. padding: 12px 16px;
  399. border-radius: var(--radius-lg);
  400. font-size: 14px;
  401. line-height: 1.6;
  402. }
  403. .chat-msg.ai .chat-bubble {
  404. background: var(--surface);
  405. border: 1px solid var(--border-light);
  406. border-bottom-left-radius: 4px;
  407. box-shadow: var(--shadow-sm);
  408. }
  409. .chat-msg.user .chat-bubble {
  410. background: var(--primary);
  411. color: white;
  412. border-bottom-right-radius: 4px;
  413. }
  414. /* ===== BIZ CARDS ===== */
  415. .biz-card {
  416. background: var(--surface);
  417. border: 1px solid var(--border);
  418. border-radius: var(--radius-md);
  419. padding: 14px;
  420. margin-top: 8px;
  421. box-shadow: var(--shadow-sm);
  422. cursor: pointer;
  423. transition: transform 0.15s, box-shadow 0.15s;
  424. }
  425. .biz-card:active { transform: scale(0.98); }
  426. .biz-card-header {
  427. display: flex; align-items: center; gap: 6px;
  428. font-weight: 700; font-size: 14px; margin-bottom: 10px;
  429. }
  430. .biz-card-header i { font-size: 18px; }
  431. .biz-card-row {
  432. display: flex; align-items: center; justify-content: space-between;
  433. padding: 5px 0; font-size: 13px; color: var(--muted);
  434. }
  435. .biz-card-row .val { font-weight: 600; color: var(--foreground); }
  436. .biz-card-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
  437. .biz-btn {
  438. display: inline-flex; align-items: center; gap: 4px;
  439. padding: 7px 12px; border-radius: var(--radius-full);
  440. border: 1px solid var(--border); background: var(--surface);
  441. font-size: 12px; font-weight: 600; color: var(--foreground);
  442. cursor: pointer; transition: all 0.15s; white-space: nowrap;
  443. font-family: inherit;
  444. }
  445. .biz-btn:active { background: var(--primary-bg); border-color: var(--primary-light); }
  446. .biz-btn i { font-size: 14px; }
  447. .biz-btn.primary { background: var(--primary); color: white; border-color: var(--primary); }
  448. .biz-btn.primary:active { background: var(--primary-dark); }
  449. .report-card { border-left: 3px solid var(--primary); }
  450. .draft-card { border-left: 3px solid var(--warning); }
  451. .draft-price {
  452. font-size: 20px; font-weight: 800; color: var(--primary); margin-top: 6px;
  453. }
  454. .draft-price small { font-size: 13px; font-weight: 500; color: var(--muted); }
  455. /* ===== QUICK ACTIONS ===== */
  456. .quick-actions {
  457. display: grid; grid-template-columns: repeat(4,1fr); gap: 8px;
  458. margin-top: 10px; padding: 10px;
  459. background: var(--surface); border-radius: var(--radius-md);
  460. border: 1px solid var(--border-light);
  461. }
  462. .quick-action {
  463. display: flex; flex-direction: column; align-items: center; gap: 4px;
  464. padding: 8px 4px; border-radius: var(--radius-sm);
  465. border: none; background: transparent; cursor: pointer;
  466. transition: background 0.15s;
  467. }
  468. .quick-action:active { background: var(--primary-bg); }
  469. .quick-action-icon {
  470. width: 36px; height: 36px; border-radius: var(--radius-sm);
  471. display: flex; align-items: center; justify-content: center;
  472. font-size: 18px;
  473. }
  474. .quick-action-label { font-size: 11px; font-weight: 600; color: var(--muted); text-align: center; }
  475. /* ===== SUMMARY BUBBLE ===== */
  476. .summary-bubble {
  477. display: flex; align-items: center; gap: 8px;
  478. padding: 10px 14px; background: var(--surface);
  479. border: 1px solid var(--border-light); border-radius: var(--radius-md);
  480. margin-bottom: 12px; font-size: 13px; color: var(--muted);
  481. cursor: pointer; transition: background 0.15s;
  482. animation: msgIn 0.3s ease both;
  483. }
  484. .summary-bubble:active { background: var(--primary-bg); }
  485. .summary-bubble i { color: var(--success); font-size: 16px; flex-shrink: 0; }
  486. .summary-bubble .text { font-weight: 600; color: var(--foreground); }
  487. /* ===== THINKING ===== */
  488. .thinking {
  489. display: flex; gap: 10px; margin-bottom: 16px;
  490. animation: msgIn 0.3s ease both;
  491. }
  492. .thinking-dots {
  493. display: flex; align-items: center; gap: 4px;
  494. padding: 14px 18px; background: var(--surface);
  495. border: 1px solid var(--border-light); border-radius: var(--radius-lg);
  496. border-bottom-left-radius: 4px; box-shadow: var(--shadow-sm);
  497. }
  498. .thinking-dots span {
  499. width: 7px; height: 7px; border-radius: 50%;
  500. background: var(--primary-light);
  501. animation: dotPulse 1.4s ease-in-out infinite;
  502. }
  503. .thinking-dots span:nth-child(2) { animation-delay: 0.2s; }
  504. .thinking-dots span:nth-child(3) { animation-delay: 0.4s; }
  505. @keyframes dotPulse {
  506. 0%,60%,100% { opacity: 0.3; transform: scale(0.8); }
  507. 30% { opacity: 1; transform: scale(1.1); }
  508. }
  509. /* ===== INPUT BAR ===== */
  510. .input-bar {
  511. position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
  512. width: 100%; max-width: 480px;
  513. background: rgba(255,255,255,0.92);
  514. backdrop-filter: blur(20px);
  515. border-top: 1px solid var(--border-light);
  516. padding: 10px 12px calc(10px + var(--safe-bottom));
  517. display: flex; align-items: center; gap: 8px; z-index: 100;
  518. }
  519. .input-field {
  520. flex: 1; height: 44px; padding: 0 16px;
  521. border-radius: var(--radius-full);
  522. border: 1px solid var(--border);
  523. background: var(--surface);
  524. font-size: 15px; font-family: inherit;
  525. color: var(--foreground); outline: none;
  526. transition: border-color 0.15s;
  527. }
  528. .input-field:focus { border-color: var(--primary-light); }
  529. .input-field::placeholder { color: var(--muted-light); }
  530. .icon-btn {
  531. width: 44px; height: 44px;
  532. border-radius: var(--radius-full); border: none;
  533. display: flex; align-items: center; justify-content: center;
  534. cursor: pointer; transition: all 0.15s; flex-shrink: 0;
  535. font-size: 22px;
  536. }
  537. .voice-btn { background: var(--surface); border: 1px solid var(--border); color: var(--muted); }
  538. .voice-btn:active { background: var(--primary-bg); }
  539. .send-btn { background: var(--primary); color: white; opacity: 0.4; pointer-events: none; }
  540. .send-btn.active { opacity: 1; pointer-events: auto; }
  541. .send-btn:active { background: var(--primary-dark); }
  542. .send-btn i { font-size: 18px; }
  543. .confirm-btn {
  544. background: var(--success); color: white; opacity: 0.4; pointer-events: none;
  545. }
  546. .confirm-btn.active { opacity: 1; pointer-events: auto; }
  547. .confirm-btn:active { background: #059669; }
  548. .confirm-btn i { font-size: 18px; }
  549. /* ===== OVERLAY & BOTTOM SHEET ===== */
  550. .overlay {
  551. position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  552. background: rgba(0,0,0,0.45); z-index: 200;
  553. opacity: 0; pointer-events: none; transition: opacity 0.3s;
  554. }
  555. .overlay.active { opacity: 1; pointer-events: auto; }
  556. .bottom-sheet {
  557. position: fixed; bottom: 0; left: 50%;
  558. transform: translateX(-50%) translateY(100%);
  559. width: 100%; max-width: 480px; max-height: 85dvh;
  560. background: var(--surface);
  561. border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  562. z-index: 210;
  563. transition: transform 0.35s cubic-bezier(0.32,0.72,0,1);
  564. overflow: hidden; display: flex; flex-direction: column;
  565. }
  566. .bottom-sheet.active { transform: translateX(-50%) translateY(0); }
  567. .sheet-handle {
  568. display: flex; justify-content: center; padding: 10px 0 6px; cursor: grab;
  569. }
  570. .sheet-handle::after {
  571. content: ''; width: 36px; height: 4px; border-radius: 2px; background: var(--border);
  572. }
  573. .sheet-header {
  574. display: flex; align-items: center; justify-content: space-between;
  575. padding: 4px 20px 12px; border-bottom: 1px solid var(--border-light);
  576. }
  577. .sheet-title {
  578. font-size: 17px; font-weight: 700;
  579. display: flex; align-items: center; gap: 8px;
  580. }
  581. .sheet-title i { font-size: 20px; }
  582. .sheet-badge {
  583. font-size: 11px; font-weight: 600; padding: 2px 8px;
  584. border-radius: var(--radius-full); background: var(--warning); color: white;
  585. }
  586. .sheet-source {
  587. font-size: 12px; color: var(--muted); padding: 6px 20px 10px;
  588. display: flex; align-items: center; gap: 4px;
  589. }
  590. .sheet-source i { font-size: 14px; }
  591. .sheet-body {
  592. flex: 1; overflow-y: auto; padding: 0 20px 20px;
  593. -webkit-overflow-scrolling: touch;
  594. }
  595. .sheet-footer {
  596. padding: 12px 20px calc(12px + var(--safe-bottom));
  597. border-top: 1px solid var(--border-light);
  598. display: flex; gap: 10px;
  599. }
  600. /* ===== FORM IN SHEET ===== */
  601. .form-section {
  602. background: var(--gray-50); border-radius: var(--radius-md);
  603. padding: 14px; margin-bottom: 14px; border: 1px solid var(--border-light);
  604. }
  605. .form-section-title {
  606. display: flex; align-items: center; justify-content: space-between;
  607. font-size: 14px; font-weight: 700; margin-bottom: 10px;
  608. }
  609. .form-section-title .edit-btn {
  610. font-size: 12px; color: var(--primary); cursor: pointer;
  611. font-weight: 600; background: none; border: none; padding: 2px 6px;
  612. font-family: inherit;
  613. }
  614. .form-row {
  615. display: flex; justify-content: space-between; align-items: center;
  616. padding: 6px 0; font-size: 14px;
  617. }
  618. .form-row .label { color: var(--muted); }
  619. .form-row .value { font-weight: 600; }
  620. .form-row .value.highlight { color: var(--primary); font-size: 16px; }
  621. /* ===== NL INPUT IN SHEET ===== */
  622. .nl-input-section {
  623. margin: 12px 0; padding: 12px;
  624. background: var(--primary-bg); border-radius: var(--radius-md);
  625. border: 1px dashed var(--primary-light);
  626. }
  627. .nl-input-label {
  628. font-size: 13px; color: var(--primary); font-weight: 600;
  629. margin-bottom: 8px; display: flex; align-items: center; gap: 6px;
  630. }
  631. .nl-input {
  632. width: 100%; min-height: 44px; padding: 10px 14px;
  633. border: 1px solid var(--primary-light); border-radius: var(--radius-sm);
  634. font-size: 14px; font-family: inherit; color: var(--foreground);
  635. background: white; outline: none; resize: none;
  636. }
  637. .nl-input::placeholder { color: var(--muted-light); }
  638. .nl-input-actions {
  639. display: flex; gap: 8px; margin-top: 8px; justify-content: flex-end;
  640. }
  641. /* ===== COST CARD ===== */
  642. .cost-card {
  643. background: var(--gray-50); border: 1px solid var(--border-light);
  644. border-radius: var(--radius-md); padding: 16px; margin-bottom: 12px;
  645. position: relative;
  646. }
  647. .cost-card.recommended {
  648. border: 2px solid var(--primary); background: var(--primary-bg);
  649. }
  650. .cost-card.recommended::before {
  651. content: '推荐'; position: absolute; top: -1px; right: 12px;
  652. background: var(--primary); color: white; font-size: 11px; font-weight: 700;
  653. padding: 2px 10px; border-radius: 0 0 8px 8px;
  654. }
  655. .cost-card-title {
  656. font-size: 15px; font-weight: 700; margin-bottom: 12px;
  657. display: flex; align-items: center; gap: 6px;
  658. }
  659. .cost-total { font-size: 28px; font-weight: 800; color: var(--primary); margin-bottom: 4px; }
  660. .cost-row {
  661. display: flex; justify-content: space-between; padding: 5px 0;
  662. font-size: 13px; color: var(--muted);
  663. }
  664. .cost-row .val { font-weight: 600; color: var(--foreground); }
  665. /* ===== COMPLIANCE ===== */
  666. .compliance {
  667. display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px;
  668. padding-top: 12px; border-top: 1px solid var(--border-light);
  669. }
  670. .compliance-badge {
  671. display: inline-flex; align-items: center; gap: 4px;
  672. padding: 4px 10px; border-radius: var(--radius-full);
  673. background: var(--success-light); font-size: 12px;
  674. font-weight: 600; color: #065F46;
  675. }
  676. .compliance-badge i { font-size: 14px; }
  677. /* ===== PROGRESS ===== */
  678. .progress-bar-wrap { margin: 10px 0; }
  679. .progress-label {
  680. display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 6px;
  681. }
  682. .progress-label .text { color: var(--muted); }
  683. .progress-label .count { font-weight: 700; color: var(--primary); }
  684. .progress-track {
  685. height: 8px; background: var(--border-light); border-radius: 4px; overflow: hidden;
  686. }
  687. .progress-fill {
  688. height: 100%; background: linear-gradient(90deg, var(--primary), var(--secondary));
  689. border-radius: 4px; transition: width 0.6s cubic-bezier(0.34,1.56,0.64,1);
  690. }
  691. /* ===== TIMELINE ===== */
  692. .timeline { padding: 0; list-style: none; }
  693. .timeline-item {
  694. display: flex; gap: 12px; padding: 8px 0; position: relative;
  695. }
  696. .timeline-item:not(:last-child)::after {
  697. content: ''; position: absolute; left: 11px; top: 28px; bottom: -4px;
  698. width: 2px; background: var(--border-light);
  699. }
  700. .timeline-dot {
  701. width: 24px; height: 24px; border-radius: 50%;
  702. display: flex; align-items: center; justify-content: center;
  703. flex-shrink: 0; background: var(--border-light); font-size: 12px;
  704. }
  705. .timeline-dot.done { background: var(--success-light); color: var(--success); }
  706. .timeline-dot.active { background: var(--warning-light); color: var(--warning); }
  707. .timeline-content { flex: 1; font-size: 13px; }
  708. .timeline-content .title { font-weight: 600; }
  709. .timeline-content .time { color: var(--muted-light); font-size: 12px; }
  710. /* ===== PERSON LIST ===== */
  711. .person-item {
  712. display: flex; align-items: center; gap: 10px;
  713. padding: 10px 0; border-bottom: 1px solid var(--border-light);
  714. }
  715. .person-item:last-child { border-bottom: none; }
  716. .person-avatar {
  717. width: 36px; height: 36px; border-radius: 50%;
  718. background: var(--primary-bg); display: flex; align-items: center;
  719. justify-content: center; font-size: 14px; font-weight: 700;
  720. color: var(--primary); flex-shrink: 0;
  721. }
  722. .person-info { flex: 1; }
  723. .person-name { font-size: 14px; font-weight: 600; }
  724. .person-detail { font-size: 12px; color: var(--muted); }
  725. .person-status {
  726. font-size: 12px; font-weight: 600; padding: 3px 10px;
  727. border-radius: var(--radius-full); white-space: nowrap;
  728. }
  729. .person-status.done { background: var(--success-light); color: #065F46; }
  730. .person-status.pending { background: var(--warning-light); color: #92400E; }
  731. .person-status.fail { background: var(--danger-light); color: #991B1B; }
  732. .person-status.review { background: var(--info-light); color: #1E40AF; }
  733. /* ===== MODAL ===== */
  734. .modal-overlay {
  735. position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  736. background: rgba(0,0,0,0.45); z-index: 300;
  737. opacity: 0; pointer-events: none; transition: opacity 0.3s;
  738. }
  739. .modal-overlay.active { opacity: 1; pointer-events: auto; }
  740. .modal {
  741. position: fixed; top: 50%; left: 50%;
  742. transform: translate(-50%,-50%) scale(0.9);
  743. width: calc(100% - 48px); max-width: 360px;
  744. background: var(--surface); border-radius: var(--radius-lg);
  745. z-index: 310; opacity: 0; pointer-events: none;
  746. transition: all 0.25s cubic-bezier(0.34,1.56,0.64,1);
  747. box-shadow: var(--shadow-xl); overflow: hidden;
  748. }
  749. .modal.active {
  750. opacity: 1; pointer-events: auto;
  751. transform: translate(-50%,-50%) scale(1);
  752. }
  753. .modal-body { padding: 24px 20px; text-align: center; }
  754. .modal-icon {
  755. width: 56px; height: 56px; border-radius: 50%;
  756. margin: 0 auto 14px; display: flex; align-items: center;
  757. justify-content: center; font-size: 28px;
  758. }
  759. .modal-icon.success { background: var(--success-light); color: var(--success); }
  760. .modal-icon.warning { background: var(--warning-light); color: var(--warning); }
  761. .modal-title { font-size: 17px; font-weight: 700; margin-bottom: 6px; }
  762. .modal-desc { font-size: 14px; color: var(--muted); line-height: 1.5; }
  763. .modal-footer {
  764. display: flex; gap: 10px; padding: 0 20px 20px;
  765. }
  766. .modal-btn {
  767. flex: 1; height: 44px; border-radius: var(--radius-sm); border: none;
  768. font-size: 15px; font-weight: 600; font-family: inherit; cursor: pointer;
  769. transition: all 0.15s;
  770. }
  771. .modal-btn.cancel { background: var(--gray-100); color: var(--foreground); }
  772. .modal-btn.confirm { background: var(--primary); color: white; }
  773. .modal-btn:active { opacity: 0.85; }
  774. /* ===== QR MODAL ===== */
  775. .qr-area {
  776. width: 180px; height: 180px; margin: 16px auto;
  777. background: white; border: 2px solid var(--border);
  778. border-radius: var(--radius-md); display: flex;
  779. align-items: center; justify-content: center;
  780. }
  781. .qr-area svg { width: 140px; height: 140px; color: var(--foreground); }
  782. .qr-actions {
  783. display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 16px;
  784. }
  785. .qr-action {
  786. display: flex; align-items: center; justify-content: center; gap: 6px;
  787. padding: 10px; border-radius: var(--radius-sm);
  788. border: 1px solid var(--border); background: var(--surface);
  789. font-size: 13px; font-weight: 600; color: var(--foreground);
  790. cursor: pointer; transition: all 0.15s; font-family: inherit;
  791. }
  792. .qr-action:active { background: var(--primary-bg); }
  793. .qr-action i { font-size: 16px; }
  794. /* ===== SIDE DRAWER ===== */
  795. .side-drawer {
  796. position: fixed; top: 0; right: 0;
  797. width: 82%; max-width: 360px; height: 100dvh;
  798. background: var(--surface); z-index: 215;
  799. transform: translateX(100%);
  800. transition: transform 0.35s cubic-bezier(0.32,0.72,0,1);
  801. display: flex; flex-direction: column;
  802. box-shadow: -10px 0 30px rgba(0,0,0,0.1);
  803. }
  804. .side-drawer.active { transform: translateX(0); }
  805. .drawer-header {
  806. padding: 20px 20px 16px; border-bottom: 1px solid var(--border-light);
  807. }
  808. .drawer-title {
  809. font-size: 18px; font-weight: 700; display: flex; align-items: center; gap: 8px;
  810. }
  811. .drawer-title i { font-size: 20px; }
  812. .drawer-body { flex: 1; overflow-y: auto; padding: 16px 20px; }
  813. .drawer-section-title {
  814. font-size: 12px; font-weight: 700; color: var(--muted);
  815. text-transform: uppercase; letter-spacing: 0.5px;
  816. margin-bottom: 10px; margin-top: 16px;
  817. }
  818. .drawer-section-title:first-child { margin-top: 0; }
  819. .msg-item {
  820. padding: 12px; border-radius: var(--radius-sm);
  821. border: 1px solid var(--border-light); margin-bottom: 8px;
  822. cursor: pointer; transition: background 0.15s;
  823. }
  824. .msg-item:active { background: var(--primary-bg); }
  825. .msg-item-header {
  826. display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px;
  827. }
  828. .msg-type {
  829. font-size: 11px; font-weight: 700; padding: 2px 8px;
  830. border-radius: var(--radius-full);
  831. }
  832. .msg-type.pending { background: var(--warning-light); color: #92400E; }
  833. .msg-type.error { background: var(--danger-light); color: #991B1B; }
  834. .msg-type.info { background: var(--info-light); color: #1E40AF; }
  835. .msg-time { font-size: 11px; color: var(--muted-light); }
  836. .msg-title { font-size: 14px; font-weight: 600; margin-bottom: 2px; }
  837. .msg-desc { font-size: 13px; color: var(--muted); }
  838. .msg-action {
  839. margin-top: 8px; display: inline-flex; align-items: center; gap: 4px;
  840. font-size: 13px; font-weight: 600; color: var(--primary);
  841. background: none; border: none; cursor: pointer; padding: 0;
  842. font-family: inherit;
  843. }
  844. .msg-action i { font-size: 14px; }
  845. /* ===== PROFILE ===== */
  846. .profile-card {
  847. background: var(--primary-bg); border-radius: var(--radius-md);
  848. padding: 16px; margin-bottom: 16px; text-align: center;
  849. }
  850. .profile-avatar-lg {
  851. width: 60px; height: 60px; border-radius: 50%;
  852. background: linear-gradient(135deg, var(--primary), var(--secondary));
  853. margin: 0 auto 10px; display: flex; align-items: center;
  854. justify-content: center; color: white; font-size: 22px; font-weight: 800;
  855. }
  856. .profile-name { font-size: 16px; font-weight: 700; }
  857. .profile-meta { font-size: 13px; color: var(--muted); margin-top: 2px; }
  858. .profile-status-badge {
  859. display: inline-flex; align-items: center; gap: 4px;
  860. padding: 3px 10px; border-radius: var(--radius-full);
  861. background: var(--success-light); color: #065F46;
  862. font-size: 12px; font-weight: 600; margin-top: 8px;
  863. }
  864. .profile-menu-item {
  865. display: flex; align-items: center; gap: 12px;
  866. padding: 14px; border-radius: var(--radius-sm);
  867. cursor: pointer; transition: background 0.15s;
  868. }
  869. .profile-menu-item:active { background: var(--primary-bg); }
  870. .profile-menu-icon {
  871. width: 36px; height: 36px; border-radius: var(--radius-sm);
  872. display: flex; align-items: center; justify-content: center;
  873. flex-shrink: 0; font-size: 18px;
  874. }
  875. .profile-menu-text { flex: 1; }
  876. .profile-menu-title { font-size: 14px; font-weight: 600; }
  877. .profile-menu-desc { font-size: 12px; color: var(--muted); }
  878. .profile-menu-arrow { color: var(--muted-light); font-size: 18px; }
  879. .profile-divider { height: 1px; background: var(--border-light); margin: 8px 0; }
  880. /* ===== WORKER REG ===== */
  881. .worker-step-indicator {
  882. display: flex; align-items: center; gap: 6px; padding: 0 20px 14px;
  883. }
  884. .worker-step {
  885. flex: 1; height: 4px; border-radius: 2px; background: var(--border-light);
  886. }
  887. .worker-step.active { background: var(--primary); }
  888. .worker-step.done { background: var(--success); }
  889. /* ===== SETTLEMENT ===== */
  890. .settlement-row {
  891. display: flex; justify-content: space-between; padding: 8px 0; font-size: 14px;
  892. }
  893. .settlement-row.total {
  894. border-top: 2px solid var(--border); margin-top: 6px;
  895. padding-top: 10px; font-weight: 700; font-size: 16px;
  896. }
  897. .settlement-row .label { color: var(--muted); }
  898. .settlement-row .val { font-weight: 600; }
  899. .settlement-row.total .val { color: var(--primary); }
  900. /* ===== ATTENDANCE ===== */
  901. .attendance-row {
  902. display: flex; align-items: center; gap: 10px;
  903. padding: 10px; border-bottom: 1px solid var(--border-light);
  904. }
  905. .attendance-avatar {
  906. width: 32px; height: 32px; border-radius: 50%;
  907. background: var(--primary-bg); display: flex; align-items: center;
  908. justify-content: center; font-size: 12px; font-weight: 700;
  909. color: var(--primary); flex-shrink: 0;
  910. }
  911. .attendance-info { flex: 1; }
  912. .attendance-name { font-size: 14px; font-weight: 600; }
  913. .attendance-role { font-size: 12px; color: var(--muted); }
  914. .attendance-stat { text-align: right; }
  915. .attendance-stat .hours { font-size: 16px; font-weight: 700; }
  916. .attendance-stat .label { font-size: 11px; color: var(--muted); }
  917. .attendance-stat .overtime { color: var(--warning); }
  918. .attendance-stat .leave { color: var(--danger); }
  919. /* ===== SWIPE INDICATOR ===== */
  920. .swipe-indicator {
  921. display: flex; align-items: center; justify-content: center;
  922. gap: 8px; padding: 6px 0; font-size: 12px; color: var(--muted-light);
  923. }
  924. .dot-indicator {
  925. display: flex; gap: 6px; justify-content: center; padding: 8px 0;
  926. }
  927. .dot-indicator span {
  928. width: 6px; height: 6px; border-radius: 50%; background: var(--border);
  929. }
  930. .dot-indicator span.active {
  931. background: var(--primary); width: 18px; border-radius: 3px;
  932. }
  933. /* ===== TOAST ===== */
  934. #toast {
  935. position: fixed; top: 80px; left: 50%;
  936. transform: translateX(-50%) translateY(-20px);
  937. background: var(--foreground); color: white;
  938. padding: 10px 20px; border-radius: var(--radius-full);
  939. font-size: 14px; font-weight: 600; z-index: 999;
  940. opacity: 0; pointer-events: none; transition: all 0.3s cubic-bezier(0.34,1.56,0.64,1);
  941. white-space: nowrap; box-shadow: var(--shadow-lg);
  942. }
  943. /* ===== CONFIG DIALOG (OVERLAY ON PROFILE) ===== */
  944. .config-overlay {
  945. position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  946. background: rgba(0,0,0,0.45); z-index: 400;
  947. opacity: 0; pointer-events: none; transition: opacity 0.3s;
  948. }
  949. .config-overlay.active { opacity: 1; pointer-events: auto; }
  950. .config-sheet {
  951. position: fixed; bottom: 0; left: 50%;
  952. transform: translateX(-50%) translateY(100%);
  953. width: 100%; max-width: 480px; max-height: 75dvh;
  954. background: var(--surface);
  955. border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  956. z-index: 410;
  957. transition: transform 0.35s cubic-bezier(0.32,0.72,0,1);
  958. overflow: hidden; display: flex; flex-direction: column;
  959. }
  960. .config-sheet.active { transform: translateX(-50%) translateY(0); }
  961. /* ===== WORKER WALLET ===== */
  962. .wallet-header {
  963. background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  964. border-radius: var(--radius-xl); padding: 24px 20px; color: white;
  965. margin-bottom: 16px; position: relative; overflow: hidden;
  966. }
  967. .wallet-header::before {
  968. content: ''; position: absolute; top: -30%; right: -20%;
  969. width: 60%; height: 80%; border-radius: 50%;
  970. background: rgba(255,255,255,0.08);
  971. }
  972. .wallet-header::after {
  973. content: ''; position: absolute; bottom: -40%; left: -10%;
  974. width: 50%; height: 70%; border-radius: 50%;
  975. background: rgba(255,255,255,0.05);
  976. }
  977. .wallet-name { font-size: 18px; font-weight: 700; position: relative; }
  978. .wallet-phone { font-size: 13px; opacity: 0.8; margin-top: 2px; position: relative; }
  979. .wallet-status {
  980. display: inline-flex; align-items: center; gap: 4px;
  981. padding: 3px 10px; border-radius: var(--radius-full);
  982. background: rgba(255,255,255,0.2); font-size: 12px; font-weight: 600;
  983. margin-top: 8px; position: relative;
  984. }
  985. .wallet-balance {
  986. margin-top: 16px; position: relative;
  987. }
  988. .wallet-balance-label { font-size: 13px; opacity: 0.8; margin-bottom: 4px; }
  989. .wallet-balance-amount {
  990. font-size: 32px; font-weight: 800; letter-spacing: -1px;
  991. font-variant-numeric: tabular-nums;
  992. }
  993. .wallet-section {
  994. background: white; border-radius: var(--radius-lg);
  995. padding: 4px 0; margin-bottom: 12px;
  996. box-shadow: var(--shadow-sm); border: 1px solid var(--border-light);
  997. }
  998. .wallet-section-title {
  999. font-size: 14px; font-weight: 700; padding: 14px 16px 8px;
  1000. display: flex; align-items: center; gap: 8px;
  1001. }
  1002. .wallet-section-title i { font-size: 18px; }
  1003. .wallet-menu-item {
  1004. display: flex; align-items: center; gap: 12px;
  1005. padding: 14px 16px; cursor: pointer; transition: background 0.15s;
  1006. }
  1007. .wallet-menu-item:active { background: var(--gray-50); }
  1008. .wallet-menu-icon {
  1009. width: 38px; height: 38px; border-radius: var(--radius-sm);
  1010. display: flex; align-items: center; justify-content: center;
  1011. flex-shrink: 0; font-size: 18px;
  1012. }
  1013. .wallet-menu-text { flex: 1; }
  1014. .wallet-menu-title { font-size: 14px; font-weight: 600; }
  1015. .wallet-menu-desc { font-size: 12px; color: var(--muted); margin-top: 1px; }
  1016. .wallet-menu-badge {
  1017. font-size: 11px; font-weight: 700; padding: 2px 8px;
  1018. border-radius: var(--radius-full); background: var(--primary-bg);
  1019. color: var(--primary);
  1020. }
  1021. .wallet-menu-arrow { color: var(--muted-light); font-size: 18px; }
  1022. .wallet-record {
  1023. display: flex; align-items: center; gap: 12px;
  1024. padding: 12px 16px; border-bottom: 1px solid var(--border-light);
  1025. }
  1026. .wallet-record:last-child { border-bottom: none; }
  1027. .wallet-record-icon {
  1028. width: 32px; height: 32px; border-radius: 50%;
  1029. background: var(--success-light); display: flex;
  1030. align-items: center; justify-content: center;
  1031. font-size: 14px; color: var(--success); flex-shrink: 0;
  1032. }
  1033. .wallet-record-info { flex: 1; }
  1034. .wallet-record-title { font-size: 14px; font-weight: 600; }
  1035. .wallet-record-meta { font-size: 12px; color: var(--muted); }
  1036. .wallet-record-amount { font-size: 15px; font-weight: 700; color: var(--success); }
  1037. .wallet-help-card {
  1038. background: var(--warning-light); border-radius: var(--radius-lg);
  1039. padding: 16px; margin-bottom: 16px; border: 1px solid rgba(245,158,11,0.2);
  1040. }
  1041. .wallet-help-title {
  1042. font-size: 14px; font-weight: 700; margin-bottom: 4px;
  1043. display: flex; align-items: center; gap: 6px;
  1044. }
  1045. /* ===== ANIMATIONS ===== */
  1046. @keyframes msgIn {
  1047. from { opacity: 0; transform: translateY(12px); }
  1048. to { opacity: 1; transform: translateY(0); }
  1049. }
  1050. @keyframes progressGrow { from { width: 0; } }
  1051. @keyframes countUp {
  1052. from { opacity: 0; transform: translateY(8px); }
  1053. to { opacity: 1; transform: translateY(0); }
  1054. }
  1055. /* ===== BOTTOM NAV ===== */
  1056. .bottom-nav {
  1057. position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
  1058. width: 100%; max-width: 480px;
  1059. background: rgba(255,255,255,0.92);
  1060. backdrop-filter: blur(20px);
  1061. border-top: 1px solid var(--border-light);
  1062. display: flex; padding: 6px 0 calc(6px + var(--safe-bottom));
  1063. z-index: 100;
  1064. }
  1065. .bottom-nav-item {
  1066. flex: 1; display: flex; flex-direction: column; align-items: center;
  1067. gap: 2px; padding: 6px 0; border: none; background: transparent;
  1068. cursor: pointer; font-family: inherit; transition: color 0.15s;
  1069. color: var(--gray-400);
  1070. }
  1071. .bottom-nav-item.active { color: var(--primary); }
  1072. .bottom-nav-item i { font-size: 22px; }
  1073. .bottom-nav-item span { font-size: 11px; font-weight: 600; }
  1074. @media (min-width: 481px) {
  1075. .app { border-left: 1px solid var(--border-light); border-right: 1px solid var(--border-light); }
  1076. }
  1077. </style>
  1078. </head>
  1079. <body>
  1080. <div class="app" id="app">
  1081. <!-- ===== LOGIN PAGE ===== -->
  1082. <div class="page login-page active" id="pageLogin">
  1083. <div class="login-visual">
  1084. <h1>智能用工,轻松管理</h1>
  1085. <p>AI驱动的企业灵活用工一站式解决方案</p>
  1086. <div class="features">
  1087. <div class="feature-item"><i class="ri-check-line"></i><span>对话式操作,无需复杂表单</span></div>
  1088. <div class="feature-item"><i class="ri-check-line"></i><span>智能草稿生成,一键确认</span></div>
  1089. <div class="feature-item"><i class="ri-check-line"></i><span>成本透明对比,精打细算</span></div>
  1090. <div class="feature-item"><i class="ri-check-line"></i><span>全流程合规,安全可追溯</span></div>
  1091. </div>
  1092. </div>
  1093. <div class="login-card">
  1094. <h2>欢迎回来</h2>
  1095. <p class="subtitle">请选择您的身份登录</p>
  1096. <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px;">
  1097. <button class="btn btn-lg btn-full" id="loginTabEnterprise" onclick="switchLoginTab('enterprise')" style="background:var(--primary);color:white;border:2px solid var(--primary);">
  1098. <i class="ri-building-line"></i> 企业登录
  1099. </button>
  1100. <button class="btn btn-lg btn-full" id="loginTabWorker" onclick="switchLoginTab('worker')" style="background:var(--surface);color:var(--gray-600);border:2px solid var(--border);">
  1101. <i class="ri-user-line"></i> 临时工登录
  1102. </button>
  1103. </div>
  1104. <!-- Enterprise Login Form -->
  1105. <div id="loginFormEnterprise">
  1106. <div class="form-group">
  1107. <label class="form-label">企业名称</label>
  1108. <input class="form-input" type="text" placeholder="请输入企业名称或统一社会信用代码">
  1109. </div>
  1110. <div class="form-group">
  1111. <label class="form-label">登录手机号</label>
  1112. <input class="form-input" type="tel" placeholder="请输入手机号">
  1113. </div>
  1114. <div class="form-group">
  1115. <label class="form-label">验证码</label>
  1116. <div style="display:flex;gap:10px;">
  1117. <input class="form-input" type="text" placeholder="请输入验证码" style="flex:1;">
  1118. <button class="btn btn-secondary" style="white-space:nowrap;">获取验证码</button>
  1119. </div>
  1120. </div>
  1121. <button class="btn btn-primary btn-lg btn-full" style="margin-top:12px;" onclick="goTo('chat')">
  1122. <i class="ri-login-box-line"></i> 登录并绑定企业
  1123. </button>
  1124. <div class="login-divider">或</div>
  1125. <button class="wechat-btn" onclick="goTo('chat')">
  1126. <i class="ri-wechat-line"></i> 微信快捷登录
  1127. </button>
  1128. </div>
  1129. <!-- Worker Login Form -->
  1130. <div id="loginFormWorker" style="display:none;">
  1131. <div class="form-group">
  1132. <label class="form-label">手机号</label>
  1133. <input class="form-input" type="tel" placeholder="请输入手机号">
  1134. </div>
  1135. <div class="form-group">
  1136. <label class="form-label">验证码</label>
  1137. <div style="display:flex;gap:10px;">
  1138. <input class="form-input" type="text" placeholder="请输入验证码" style="flex:1;">
  1139. <button class="btn btn-secondary" style="white-space:nowrap;">获取验证码</button>
  1140. </div>
  1141. </div>
  1142. <button class="btn btn-primary btn-lg btn-full" style="margin-top:12px;" onclick="goTo('worker')">
  1143. <i class="ri-user-add-line"></i> 登记并扫码入场
  1144. </button>
  1145. <p style="text-align:center;margin-top:16px;font-size:13px;color:var(--gray-500);">
  1146. 首次登录将自动创建临时工档案
  1147. </p>
  1148. </div>
  1149. <p style="text-align:center;margin-top:16px;font-size:13px;color:var(--gray-500);">
  1150. 登录即同意 <a href="#" style="color:var(--primary);">服务协议</a> 和 <a href="#" style="color:var(--primary);">隐私政策</a>
  1151. </p>
  1152. </div>
  1153. </div>
  1154. <!-- ===== CHAT PAGE ===== -->
  1155. <div class="page chat-page" id="pageChat">
  1156. <div class="top-nav">
  1157. <div class="top-nav-title">
  1158. <button class="nav-btn" onclick="toggleSidebar()" style="width:36px;height:36px;font-size:20px;">
  1159. <i class="ri-menu-line"></i>
  1160. </button>
  1161. 智能用工助手
  1162. </div>
  1163. <div class="top-nav-actions">
  1164. <button class="nav-btn" onclick="startNewChat()" aria-label="新对话">
  1165. <i class="ri-add-line"></i>
  1166. </button>
  1167. <button class="nav-btn" onclick="toggleDrawer('message')" aria-label="消息">
  1168. <i class="ri-notification-3-line"></i>
  1169. <span class="nav-badge">2</span>
  1170. </button>
  1171. <div class="nav-avatar" onclick="toggleDrawer('profile')">张</div>
  1172. </div>
  1173. </div>
  1174. <div class="chat-layout">
  1175. <div class="chat-sidebar" id="chatSidebar">
  1176. <div class="sidebar-header">
  1177. <h3>对话列表</h3>
  1178. <button class="new-chat-btn" onclick="startNewChat()"><i class="ri-add-line"></i></button>
  1179. </div>
  1180. <div class="chat-list" id="chatList">
  1181. <div class="chat-item active" onclick="switchChat(this,'employment')">
  1182. <div class="chat-item-title">用工需求咨询</div>
  1183. <div class="chat-item-time">今天 14:30</div>
  1184. </div>
  1185. <div class="chat-item" onclick="switchChat(this,'knowledge')">
  1186. <div class="chat-item-title">用工知识咨询</div>
  1187. <div class="chat-item-time">今天 10:15</div>
  1188. </div>
  1189. <div class="chat-item" onclick="switchChat(this,'order')">
  1190. <div class="chat-item-title">用工订单管理</div>
  1191. <div class="chat-item-time">昨天 16:20</div>
  1192. </div>
  1193. <div class="chat-item" onclick="switchChat(this,'cost')">
  1194. <div class="chat-item-title">成本测算</div>
  1195. <div class="chat-item-time">3天前</div>
  1196. </div>
  1197. <div class="chat-item" onclick="switchChat(this,'attendance')">
  1198. <div class="chat-item-title">现场考勤记录</div>
  1199. <div class="chat-item-time">3天前</div>
  1200. </div>
  1201. <div class="chat-item" onclick="switchChat(this,'emergency')">
  1202. <div class="chat-item-title">紧急事件处理</div>
  1203. <div class="chat-item-time">1周前</div>
  1204. </div>
  1205. </div>
  1206. </div>
  1207. <div class="chat-main">
  1208. <div class="chat-area" id="chatArea"></div>
  1209. </div>
  1210. </div>
  1211. <div class="input-bar">
  1212. <button class="icon-btn voice-btn" onclick="showToast('按住说话...')"><i class="ri-mic-line"></i></button>
  1213. <input class="input-field" id="chatInput" type="text" placeholder="输入需求或按住说话..." oninput="toggleSendBtn()" onkeydown="if(event.key==='Enter')sendMsg()">
  1214. <button class="icon-btn send-btn" id="sendBtn" onclick="sendMsg()"><i class="ri-send-plane-fill"></i></button>
  1215. </div>
  1216. </div>
  1217. <!-- ===== WORKER REG PAGE ===== -->
  1218. <div class="page" id="pageWorker" style="background:var(--gray-50);overflow-y:auto;">
  1219. <div class="top-nav">
  1220. <div class="top-nav-title">
  1221. <button class="nav-btn" onclick="goTo('chat')" style="width:36px;height:36px;font-size:20px;">
  1222. <i class="ri-arrow-left-line"></i>
  1223. </button>
  1224. 临时工登记
  1225. </div>
  1226. <div class="top-nav-actions"></div>
  1227. </div>
  1228. <div style="padding:calc(var(--nav-h) + var(--safe-top) + 16px) 20px 20px;">
  1229. <div style="background:white;border-radius:var(--radius-xl);padding:24px;box-shadow:var(--shadow-lg);margin-bottom:16px;">
  1230. <div style="text-align:center;margin-bottom:24px;">
  1231. <div style="width:64px;height:64px;border-radius:50%;background:var(--primary-bg);margin:0 auto 12px;display:flex;align-items:center;justify-content:center;font-size:28px;color:var(--primary);">
  1232. <i class="ri-user-add-line"></i>
  1233. </div>
  1234. <h2 style="font-size:20px;font-weight:700;">临时工登记</h2>
  1235. <p style="font-size:14px;color:var(--muted);">请填写您的个人信息完成登记</p>
  1236. </div>
  1237. <div class="form-group">
  1238. <label class="form-label">真实姓名 <span style="color:var(--danger);">*</span></label>
  1239. <input class="form-input" placeholder="请输入身份证上的姓名">
  1240. </div>
  1241. <div class="form-group">
  1242. <label class="form-label">身份证号 <span style="color:var(--danger);">*</span></label>
  1243. <input class="form-input" placeholder="请输入18位身份证号码">
  1244. </div>
  1245. <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
  1246. <div class="form-group">
  1247. <label class="form-label">手机号 <span style="color:var(--danger);">*</span></label>
  1248. <input class="form-input" placeholder="请输入手机号">
  1249. </div>
  1250. <div class="form-group">
  1251. <label class="form-label">验证码 <span style="color:var(--danger);">*</span></label>
  1252. <input class="form-input" placeholder="请输入验证码">
  1253. </div>
  1254. </div>
  1255. <div class="form-group">
  1256. <label class="form-label">银行卡号 <span style="color:var(--danger);">*</span></label>
  1257. <input class="form-input" placeholder="请输入银行卡号">
  1258. </div>
  1259. <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
  1260. <div class="form-group">
  1261. <label class="form-label">开户银行 <span style="color:var(--danger);">*</span></label>
  1262. <input class="form-input" placeholder="请输入开户银行">
  1263. </div>
  1264. <div class="form-group">
  1265. <label class="form-label">支行名称</label>
  1266. <input class="form-input" placeholder="请输入支行名称">
  1267. </div>
  1268. </div>
  1269. <label style="display:flex;align-items:flex-start;gap:8px;cursor:pointer;margin-bottom:16px;">
  1270. <input type="checkbox" style="margin-top:4px;">
  1271. <span style="font-size:13px;color:var(--gray-600);">
  1272. 我已阅读并同意 <a href="#" style="color:var(--primary);">《电子劳动合同》</a> 和 <a href="#" style="color:var(--primary);">《隐私政策》</a>
  1273. </span>
  1274. </label>
  1275. <button class="btn btn-primary btn-lg btn-full" onclick="showToast('登记成功!');goTo('wallet')">
  1276. <i class="ri-check-line"></i> 提交登记
  1277. </button>
  1278. <p style="text-align:center;margin-top:12px;font-size:12px;color:var(--gray-400);">
  1279. 您的信息将被加密存储,仅用于本次用工服务
  1280. </p>
  1281. </div>
  1282. </div>
  1283. </div>
  1284. <!-- ===== WALLET PAGE (临时工端) ===== -->
  1285. <div class="page" id="pageWallet" style="background:var(--gray-50);overflow-y:auto;">
  1286. <div class="top-nav">
  1287. <div class="top-nav-title">
  1288. <button class="nav-btn" onclick="goTo('worker')" style="width:36px;height:36px;font-size:20px;">
  1289. <i class="ri-arrow-left-line"></i>
  1290. </button>
  1291. 我的钱包
  1292. </div>
  1293. <div class="top-nav-actions">
  1294. <button class="nav-btn" onclick="showToast('已刷新')"><i class="ri-refresh-line"></i></button>
  1295. </div>
  1296. </div>
  1297. <div style="padding:calc(var(--nav-h) + var(--safe-top) + 16px) 16px 40px;">
  1298. <div class="wallet-header">
  1299. <div class="wallet-name">王五</div>
  1300. <div class="wallet-phone">137****9012</div>
  1301. <div class="wallet-status"><i class="ri-check-line"></i> 已实名核验</div>
  1302. <div class="wallet-balance">
  1303. <div class="wallet-balance-label">累计薪资(元)</div>
  1304. <div class="wallet-balance-amount" id="salaryAmount">¥0</div>
  1305. </div>
  1306. </div>
  1307. <div class="wallet-section">
  1308. <div class="wallet-section-title"><i class="ri-wallet-3-line" style="color:var(--primary);"></i> 我的钱包</div>
  1309. <div class="wallet-menu-item" onclick="showToast('电子合同详情')">
  1310. <div class="wallet-menu-icon" style="background:var(--info-light);"><i class="ri-file-text-line" style="color:var(--info);"></i></div>
  1311. <div class="wallet-menu-text">
  1312. <div class="wallet-menu-title">电子合同</div>
  1313. <div class="wallet-menu-desc">2份已签署</div>
  1314. </div>
  1315. <div class="wallet-menu-badge">2份</div>
  1316. <div class="wallet-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1317. </div>
  1318. <div class="wallet-menu-item" onclick="showToast('薪资明细详情')">
  1319. <div class="wallet-menu-icon" style="background:var(--success-light);"><i class="ri-money-cny-circle-line" style="color:var(--success);"></i></div>
  1320. <div class="wallet-menu-text">
  1321. <div class="wallet-menu-title">薪资明细</div>
  1322. <div class="wallet-menu-desc">累计 ¥3,500</div>
  1323. </div>
  1324. <div class="wallet-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1325. </div>
  1326. <div class="wallet-menu-item" onclick="showToast('完税证明下载')">
  1327. <div class="wallet-menu-icon" style="background:var(--warning-light);"><i class="ri-file-list-2-line" style="color:var(--warning);"></i></div>
  1328. <div class="wallet-menu-text">
  1329. <div class="wallet-menu-title">完税证明</div>
  1330. <div class="wallet-menu-desc">2024年度</div>
  1331. </div>
  1332. <div class="wallet-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1333. </div>
  1334. </div>
  1335. <div class="wallet-section">
  1336. <div class="wallet-section-title"><i class="ri-file-list-line" style="color:var(--primary);"></i> 我的做工记录</div>
  1337. <div class="wallet-record">
  1338. <div class="wallet-record-icon"><i class="ri-checkbox-circle-line"></i></div>
  1339. <div class="wallet-record-info">
  1340. <div class="wallet-record-title">浦东仓库搬运</div>
  1341. <div class="wallet-record-meta">01-20 · 已完成</div>
  1342. </div>
  1343. <div class="wallet-record-amount">¥1,000</div>
  1344. </div>
  1345. <div class="wallet-record">
  1346. <div class="wallet-record-icon"><i class="ri-checkbox-circle-line"></i></div>
  1347. <div class="wallet-record-info">
  1348. <div class="wallet-record-title">虹桥活动执行</div>
  1349. <div class="wallet-record-meta">01-15 · 已完成</div>
  1350. </div>
  1351. <div class="wallet-record-amount">¥800</div>
  1352. </div>
  1353. </div>
  1354. <div class="wallet-help-card">
  1355. <div class="wallet-help-title"><i class="ri-lightbulb-line" style="color:var(--warning);"></i> 有劳资纠纷或疑问?</div>
  1356. <button class="btn btn-primary btn-sm" onclick="showToast('已转接平台客服')" style="margin-top:8px;">
  1357. <i class="ri-customer-service-2-line"></i> 联系平台客服
  1358. </button>
  1359. </div>
  1360. </div>
  1361. </div>
  1362. <!-- ===== PROFILE PAGE ===== -->
  1363. <div class="page" id="pageProfile" style="background:var(--gray-50);overflow-y:auto;">
  1364. <div class="top-nav">
  1365. <div class="top-nav-title">企业管理中枢</div>
  1366. <div class="top-nav-actions">
  1367. <button class="nav-btn" onclick="toggleDrawer('message')"><i class="ri-notification-3-line"></i><span class="nav-badge">2</span></button>
  1368. </div>
  1369. </div>
  1370. <div style="padding:calc(var(--nav-h) + var(--safe-top) + 16px) 16px 100px;">
  1371. <div class="profile-card">
  1372. <div class="profile-avatar-lg">张</div>
  1373. <div class="profile-name">某某科技有限公司</div>
  1374. <div class="profile-meta">91310000...</div>
  1375. <div class="profile-status-badge"><i class="ri-check-line"></i> 已认证</div>
  1376. </div>
  1377. <div class="drawer-section-title">消息与待办中心</div>
  1378. <div class="profile-menu-item" onclick="toggleDrawer('message')">
  1379. <div class="profile-menu-icon" style="background:var(--warning-light);"><i class="ri-notification-3-line" style="color:var(--warning);"></i></div>
  1380. <div class="profile-menu-text"><div class="profile-menu-title">消息与待办中心</div><div class="profile-menu-desc">待确认 2 条</div></div>
  1381. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1382. </div>
  1383. <div class="profile-divider"></div>
  1384. <div class="drawer-section-title">智能偏好设置</div>
  1385. <div class="profile-menu-item" onclick="openConfig('workType')">
  1386. <div class="profile-menu-icon" style="background:var(--info-light);"><i class="ri-tools-line" style="color:var(--info);"></i></div>
  1387. <div class="profile-menu-text"><div class="profile-menu-title">常用工种与薪资基准</div></div>
  1388. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1389. </div>
  1390. <div class="profile-menu-item" onclick="openConfig('insurance')">
  1391. <div class="profile-menu-icon" style="background:var(--success-light);"><i class="ri-shield-check-line" style="color:var(--success);"></i></div>
  1392. <div class="profile-menu-text"><div class="profile-menu-title">默认保险方案偏好</div><div class="profile-menu-desc">已配置</div></div>
  1393. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1394. </div>
  1395. <div class="profile-menu-item" onclick="openConfig('payment')">
  1396. <div class="profile-menu-icon" style="background:var(--warning-light);"><i class="ri-calendar-check-line" style="color:var(--warning);"></i></div>
  1397. <div class="profile-menu-text"><div class="profile-menu-title">常规发薪日与结算周期</div></div>
  1398. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1399. </div>
  1400. <div class="profile-divider"></div>
  1401. <div class="drawer-section-title">财务与账户</div>
  1402. <div class="profile-menu-item">
  1403. <div class="profile-menu-icon" style="background:var(--danger-light);"><i class="ri-bank-card-line" style="color:var(--danger);"></i></div>
  1404. <div class="profile-menu-text"><div class="profile-menu-title">对公账户与打款通道</div></div>
  1405. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1406. </div>
  1407. <div class="profile-menu-item">
  1408. <div class="profile-menu-icon" style="background:var(--primary-bg);"><i class="ri-file-list-2-line" style="color:var(--primary);"></i></div>
  1409. <div class="profile-menu-text"><div class="profile-menu-title">企业开票抬头与税控</div></div>
  1410. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1411. </div>
  1412. <div class="profile-menu-item">
  1413. <div class="profile-menu-icon" style="background:var(--gray-100);"><i class="ri-wallet-3-line" style="color:var(--gray-600);"></i></div>
  1414. <div class="profile-menu-text"><div class="profile-menu-title">平台余额与充值管理</div></div>
  1415. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1416. </div>
  1417. <div class="profile-divider"></div>
  1418. <div class="drawer-section-title">合规与安全审计</div>
  1419. <div class="profile-menu-item">
  1420. <div class="profile-menu-icon" style="background:var(--primary-bg);"><i class="ri-file-paper-2-line" style="color:var(--primary);"></i></div>
  1421. <div class="profile-menu-text"><div class="profile-menu-title">历史合同与电子签章归档</div></div>
  1422. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1423. </div>
  1424. <div class="profile-menu-item">
  1425. <div class="profile-menu-icon" style="background:var(--info-light);"><i class="ri-search-eye-line" style="color:var(--info);"></i></div>
  1426. <div class="profile-menu-text"><div class="profile-menu-title">操作日志与合规证据链导出</div></div>
  1427. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1428. </div>
  1429. <div class="profile-menu-item">
  1430. <div class="profile-menu-icon" style="background:var(--success-light);"><i class="ri-notification-3-line" style="color:var(--success);"></i></div>
  1431. <div class="profile-menu-text"><div class="profile-menu-title">关键节点消息通知设置</div></div>
  1432. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1433. </div>
  1434. <div class="profile-divider"></div>
  1435. <div class="drawer-section-title">系统设置与帮助</div>
  1436. <div style="display:flex;gap:8px;flex-wrap:wrap;">
  1437. <button class="btn btn-secondary btn-sm"><i class="ri-information-line"></i> 关于我们</button>
  1438. <button class="btn btn-secondary btn-sm"><i class="ri-question-line"></i> 常见问题</button>
  1439. <button class="btn btn-secondary btn-sm"><i class="ri-customer-service-2-line"></i> 联系客服</button>
  1440. </div>
  1441. <div style="margin-top:24px;padding-top:16px;border-top:1px solid var(--border-light);">
  1442. <button class="btn btn-secondary btn-lg btn-full" onclick="goTo('login')" style="color:var(--danger);">
  1443. <i class="ri-logout-box-r-line"></i> 退出账号
  1444. </button>
  1445. </div>
  1446. </div>
  1447. </div>
  1448. <!-- ===== BOTTOM NAV ===== -->
  1449. <div class="bottom-nav" id="bottomNav">
  1450. <button class="bottom-nav-item active" onclick="goTo('chat')" data-page="chat">
  1451. <i class="ri-chat-3-line"></i>
  1452. <span>对话</span>
  1453. </button>
  1454. <button class="bottom-nav-item" onclick="goTo('worker')" data-page="worker">
  1455. <i class="ri-user-add-line"></i>
  1456. <span>临时工端</span>
  1457. </button>
  1458. <button class="bottom-nav-item" onclick="goTo('profile')" data-page="profile">
  1459. <i class="ri-user-3-line"></i>
  1460. <span>我的</span>
  1461. </button>
  1462. </div>
  1463. <!-- ===== PROFILE PAGE (inline in drawer) ===== -->
  1464. <!-- We'll handle profile as a drawer that can be triggered -->
  1465. <!-- ===== OVERLAY ===== -->
  1466. <div class="overlay" id="overlay" onclick="closeAll()"></div>
  1467. <!-- ===== BOTTOM SHEET: DRAFT ===== -->
  1468. <div class="bottom-sheet" id="sheetDraft">
  1469. <div class="sheet-handle"></div>
  1470. <div class="sheet-header">
  1471. <div class="sheet-title">
  1472. <i class="ri-file-text-line" style="color:var(--warning);"></i>
  1473. 用工草稿
  1474. <span class="sheet-badge">待确认</span>
  1475. </div>
  1476. </div>
  1477. <div class="sheet-source"><i class="ri-links-line"></i> 来源:AI对话 · 浦东仓库需求</div>
  1478. <div class="sheet-body">
  1479. <div class="form-section">
  1480. <div class="form-section-title">
  1481. 基础信息
  1482. <button class="edit-btn" onclick="showToast('编辑模式已开启')">编辑</button>
  1483. </div>
  1484. <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
  1485. <div class="form-row"><span class="label">用工人数</span><span class="value">10 人</span></div>
  1486. <div class="form-row"><span class="label">工作天数</span><span class="value">2 天</span></div>
  1487. <div class="form-row"><span class="label">岗位类型</span><span class="value">搬运工</span></div>
  1488. <div class="form-row"><span class="label">工作地点</span><span class="value">浦东新区</span></div>
  1489. </div>
  1490. </div>
  1491. <div class="form-section">
  1492. <div class="form-section-title">
  1493. 岗位要求
  1494. <button class="edit-btn" onclick="showToast('编辑模式已开启')">编辑</button>
  1495. </div>
  1496. <div style="font-size:13px;color:var(--muted);line-height:1.6;">
  1497. <div>• 年龄18-45岁,身体健康</div>
  1498. <div>• 有搬运经验优先</div>
  1499. </div>
  1500. </div>
  1501. <div class="nl-input-section">
  1502. <div class="nl-input-label"><i class="ri-chat-3-line"></i> 或直接告诉我要改什么:</div>
  1503. <textarea class="nl-input" rows="2" placeholder="例如:人数改成8个,加个叉车工" id="draftNlInput" oninput="toggleDraftConfirm()"></textarea>
  1504. <div class="nl-input-actions">
  1505. <button class="biz-btn" onclick="showToast('已发送修改')"><i class="ri-send-plane-fill"></i> 发送</button>
  1506. <button class="biz-btn primary" id="draftConfirmBtn" onclick="confirmNlEdit()" style="display:none;"><i class="ri-check-line"></i> 确认修改</button>
  1507. </div>
  1508. </div>
  1509. <div class="form-section" style="background:var(--primary-bg);border-color:var(--primary-light);">
  1510. <div class="form-section-title" style="margin-bottom:6px;">预估成本 <span style="font-size:12px;color:var(--muted);font-weight:400;">实时联动</span></div>
  1511. <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
  1512. <div class="form-row"><span class="label">总支出</span><span class="value highlight">¥12,800</span></div>
  1513. <div class="form-row"><span class="label">人均</span><span class="value">¥640/天</span></div>
  1514. </div>
  1515. </div>
  1516. </div>
  1517. <div class="sheet-footer">
  1518. <button class="btn btn-secondary btn-lg" style="flex:1;" onclick="showToast('已重新生成草稿')">重新生成</button>
  1519. <button class="btn btn-primary btn-lg" style="flex:1;" onclick="confirmDraft()">确认此方案</button>
  1520. </div>
  1521. </div>
  1522. <!-- ===== BOTTOM SHEET: COST ===== -->
  1523. <div class="bottom-sheet" id="sheetCost">
  1524. <div class="sheet-handle"></div>
  1525. <div class="sheet-header">
  1526. <div class="sheet-title"><i class="ri-money-cny-circle-line" style="color:var(--primary);"></i> 成本对比</div>
  1527. <div class="swipe-indicator"><i class="ri-arrow-left-s-line"></i> 滑动 <i class="ri-arrow-right-s-line"></i></div>
  1528. </div>
  1529. <div class="sheet-source"><i class="ri-links-line"></i> 浦东仓库搬运 · 10人×2天</div>
  1530. <div class="sheet-body">
  1531. <div class="cost-card recommended">
  1532. <div class="cost-card-title"><i class="ri-star-line" style="color:var(--primary);"></i> 合规优先 (A)</div>
  1533. <div class="cost-total">¥12,800</div>
  1534. <div class="cost-row"><span>人均成本</span><span class="val">¥640/天</span></div>
  1535. <div class="cost-row"><span>到手金额</span><span class="val">¥500/天</span></div>
  1536. <div style="border-top:1px solid var(--border-light);margin-top:8px;padding-top:8px;">
  1537. <div class="cost-row"><span>劳务费</span><span class="val">¥10,000</span></div>
  1538. <div class="cost-row"><span>服务费(8%)</span><span class="val">¥800</span></div>
  1539. <div class="cost-row"><span>保险(高档)</span><span class="val">¥200</span></div>
  1540. <div class="cost-row"><span>税费代征</span><span class="val">¥1,800</span></div>
  1541. </div>
  1542. <div class="compliance">
  1543. <span class="compliance-badge"><i class="ri-check-line"></i> 业务真实</span>
  1544. <span class="compliance-badge"><i class="ri-check-line"></i> 资金合规</span>
  1545. <span class="compliance-badge"><i class="ri-check-line"></i> 个税申报</span>
  1546. </div>
  1547. </div>
  1548. <div class="cost-card" style="opacity:0.6;">
  1549. <div class="cost-card-title"><i class="ri-information-line" style="color:var(--muted);"></i> 传统用工 (B)</div>
  1550. <div class="cost-total" style="color:var(--muted);">¥15,200</div>
  1551. <div class="cost-row"><span>人均成本</span><span class="val">¥760/天</span></div>
  1552. </div>
  1553. <div class="dot-indicator"><span class="active"></span><span></span><span></span></div>
  1554. </div>
  1555. <div class="sheet-footer">
  1556. <button class="btn btn-secondary btn-lg" style="flex:1;" onclick="showToast('已导出对比报告')">对比传统</button>
  1557. <button class="btn btn-primary btn-lg" style="flex:1;" onclick="confirmCost()">确认此方案</button>
  1558. </div>
  1559. </div>
  1560. <!-- ===== BOTTOM SHEET: PROGRESS ===== -->
  1561. <div class="bottom-sheet" id="sheetProgress">
  1562. <div class="sheet-handle"></div>
  1563. <div class="sheet-header">
  1564. <div class="sheet-title"><i class="ri-line-chart-line" style="color:var(--primary);"></i> 进度管理</div>
  1565. </div>
  1566. <div class="sheet-source"><i class="ri-links-line"></i> 浦东仓库搬运 BATCH-001</div>
  1567. <div class="sheet-body">
  1568. <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:16px;">
  1569. <div style="text-align:center;padding:10px 4px;background:var(--gray-50);border-radius:var(--radius-sm);">
  1570. <div style="font-size:22px;font-weight:800;color:var(--warning);">3</div>
  1571. <div style="font-size:11px;color:var(--muted);">待登记</div>
  1572. </div>
  1573. <div style="text-align:center;padding:10px 4px;background:var(--gray-50);border-radius:var(--radius-sm);">
  1574. <div style="font-size:22px;font-weight:800;color:var(--secondary);">4</div>
  1575. <div style="font-size:11px;color:var(--muted);">登记中</div>
  1576. </div>
  1577. <div style="text-align:center;padding:10px 4px;background:var(--gray-50);border-radius:var(--radius-sm);">
  1578. <div style="font-size:22px;font-weight:800;color:var(--success);">3</div>
  1579. <div style="font-size:11px;color:var(--muted);">已完成</div>
  1580. </div>
  1581. <div style="text-align:center;padding:10px 4px;background:var(--primary-bg);border-radius:var(--radius-sm);">
  1582. <div style="font-size:22px;font-weight:800;color:var(--primary);">10</div>
  1583. <div style="font-size:11px;color:var(--muted);">总计</div>
  1584. </div>
  1585. </div>
  1586. <div class="progress-bar-wrap">
  1587. <div class="progress-label"><span class="text">登记进度</span><span class="count">7/10</span></div>
  1588. <div class="progress-track"><div class="progress-fill" style="width:70%;animation:progressGrow 1s ease both;"></div></div>
  1589. </div>
  1590. <div style="margin-top:16px;">
  1591. <div style="font-size:14px;font-weight:700;margin-bottom:10px;">办理流程</div>
  1592. <ul class="timeline">
  1593. <li class="timeline-item"><div class="timeline-dot done"><i class="ri-check-line"></i></div><div class="timeline-content"><div class="title">草稿创建</div><div class="time">01-15 14:30</div></div></li>
  1594. <li class="timeline-item"><div class="timeline-dot done"><i class="ri-check-line"></i></div><div class="timeline-content"><div class="title">方案确认</div><div class="time">01-15 14:35</div></div></li>
  1595. <li class="timeline-item"><div class="timeline-dot active"><i class="ri-time-line"></i></div><div class="timeline-content"><div class="title">扫码登记 <span style="color:var(--primary);">进行中 7/10</span></div></div></li>
  1596. <li class="timeline-item"><div class="timeline-dot"></div><div class="timeline-content"><div class="title" style="color:var(--muted-light);">企业审核</div></div></li>
  1597. <li class="timeline-item"><div class="timeline-dot"></div><div class="timeline-content"><div class="title" style="color:var(--muted-light);">合同签署</div></div></li>
  1598. <li class="timeline-item"><div class="timeline-dot"></div><div class="timeline-content"><div class="title" style="color:var(--muted-light);">开始用工</div></div></li>
  1599. </ul>
  1600. </div>
  1601. <div style="margin-top:16px;">
  1602. <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;">
  1603. <div style="font-size:14px;font-weight:700;">人员列表</div>
  1604. <button class="biz-btn" onclick="showToast('已刷新')" style="font-size:11px;padding:4px 8px;"><i class="ri-refresh-line"></i> 刷新</button>
  1605. </div>
  1606. <div class="person-item"><div class="person-avatar">张</div><div class="person-info"><div class="person-name">张三</div><div class="person-detail">138****1234</div></div><span class="person-status done">已完成</span></div>
  1607. <div class="person-item"><div class="person-avatar">李</div><div class="person-info"><div class="person-name">李四</div><div class="person-detail">139****5678</div></div><span class="person-status done">已完成</span></div>
  1608. <div class="person-item"><div class="person-avatar">王</div><div class="person-info"><div class="person-name">王五</div><div class="person-detail">137****9012</div></div><span class="person-status fail">核验失败</span></div>
  1609. <div class="person-item"><div class="person-avatar">赵</div><div class="person-info"><div class="person-name">赵六</div><div class="person-detail">136****3456</div></div><span class="person-status pending">待登记</span></div>
  1610. <div class="person-item"><div class="person-avatar">钱</div><div class="person-info"><div class="person-name">钱七</div><div class="person-detail">135****7890</div></div><span class="person-status review">审核中</span></div>
  1611. </div>
  1612. </div>
  1613. <div class="sheet-footer">
  1614. <button class="btn btn-secondary btn-lg" style="flex:1;" onclick="showToast('已查看全部')">查看全部</button>
  1615. <button class="btn btn-primary btn-lg" style="flex:1;" onclick="showToast('已发送催办')">催办未登记</button>
  1616. </div>
  1617. </div>
  1618. <!-- ===== BOTTOM SHEET: SETTLEMENT ===== -->
  1619. <div class="bottom-sheet" id="sheetSettlement">
  1620. <div class="sheet-handle"></div>
  1621. <div class="sheet-header">
  1622. <div class="sheet-title"><i class="ri-bank-card-line" style="color:var(--primary);"></i> 结算确认单 <span class="sheet-badge" style="background:var(--danger);">待支付</span></div>
  1623. </div>
  1624. <div class="sheet-source"><i class="ri-links-line"></i> 浦东仓库搬运 BATCH-001</div>
  1625. <div class="sheet-body">
  1626. <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:14px;">
  1627. <div style="text-align:center;padding:10px;background:var(--gray-50);border-radius:var(--radius-sm);">
  1628. <div style="font-size:18px;font-weight:800;color:var(--primary);">¥50,400</div>
  1629. <div style="font-size:11px;color:var(--muted);">实发总额</div>
  1630. </div>
  1631. <div style="text-align:center;padding:10px;background:var(--danger-light);border-radius:var(--radius-sm);">
  1632. <div style="font-size:18px;font-weight:800;color:var(--danger);">-¥2,400</div>
  1633. <div style="font-size:11px;color:var(--muted);">扣款/个税</div>
  1634. </div>
  1635. <div style="text-align:center;padding:10px;background:var(--gray-50);border-radius:var(--radius-sm);">
  1636. <div style="font-size:18px;font-weight:800;color:var(--primary);">¥52,800</div>
  1637. <div style="font-size:11px;color:var(--muted);">应发总额</div>
  1638. </div>
  1639. </div>
  1640. <div class="form-section">
  1641. <div class="form-section-title">资金总览</div>
  1642. <div class="settlement-row"><span class="label">实发总额(共10人)</span><span class="val">¥50,400</span></div>
  1643. <div class="settlement-row"><span class="label">平台服务费(8%)</span><span class="val">¥4,032</span></div>
  1644. <div class="settlement-row"><span class="label">预计开票额</span><span class="val">¥54,432</span></div>
  1645. <div class="settlement-row total"><span class="label">总支出</span><span class="val">¥54,432</span></div>
  1646. </div>
  1647. <div class="compliance">
  1648. <span class="compliance-badge"><i class="ri-check-line"></i> 业务真实</span>
  1649. <span class="compliance-badge"><i class="ri-check-line"></i> 资金合规</span>
  1650. <span class="compliance-badge"><i class="ri-check-line"></i> 个税已申报</span>
  1651. </div>
  1652. <div style="font-size:12px;color:var(--muted);margin-top:8px;text-align:center;">本单据符合五流合一,可全额税前扣除</div>
  1653. </div>
  1654. <div class="sheet-footer">
  1655. <button class="btn btn-secondary btn-lg" style="flex:1;" onclick="showToast('已导出Excel')"><i class="ri-download-line"></i> 导出</button>
  1656. <button class="btn btn-primary btn-lg" style="flex:1;" onclick="showPayment()">确认并支付</button>
  1657. </div>
  1658. </div>
  1659. <!-- ===== BOTTOM SHEET: ATTENDANCE ===== -->
  1660. <div class="bottom-sheet" id="sheetAttendant">
  1661. <div class="sheet-handle"></div>
  1662. <div class="sheet-header">
  1663. <div class="sheet-title"><i class="ri-group-line" style="color:var(--primary);"></i> 今日考勤核对 <span style="font-size:12px;font-weight:400;color:var(--muted);">2024-01-20</span></div>
  1664. </div>
  1665. <div class="sheet-source">批次:浦东仓库搬运 (BATCH-2024-001)</div>
  1666. <div class="sheet-body">
  1667. <div style="display:flex;gap:8px;margin-bottom:16px;">
  1668. <div style="flex:1;text-align:center;padding:8px;background:var(--primary-bg);border-radius:var(--radius-sm);"><div style="font-size:18px;font-weight:800;color:var(--primary);">10</div><div style="font-size:11px;color:var(--muted);">总人数</div></div>
  1669. <div style="flex:1;text-align:center;padding:8px;background:var(--success-light);border-radius:var(--radius-sm);"><div style="font-size:18px;font-weight:800;color:var(--success);">8</div><div style="font-size:11px;color:var(--muted);">正常</div></div>
  1670. <div style="flex:1;text-align:center;padding:8px;background:var(--warning-light);border-radius:var(--radius-sm);"><div style="font-size:18px;font-weight:800;color:var(--warning);">1</div><div style="font-size:11px;color:var(--muted);">加班</div></div>
  1671. <div style="flex:1;text-align:center;padding:8px;background:var(--danger-light);border-radius:var(--radius-sm);"><div style="font-size:18px;font-weight:800;color:var(--danger);">1</div><div style="font-size:11px;color:var(--muted);">请假</div></div>
  1672. </div>
  1673. <div style="background:var(--gray-50);border-radius:var(--radius-md);overflow:hidden;border:1px solid var(--border-light);">
  1674. <div class="attendance-row"><div class="attendance-avatar">张</div><div class="attendance-info"><div class="attendance-name">张三</div><div class="attendance-role">搬运</div></div><div class="attendance-stat"><div class="hours leave">请假</div></div></div>
  1675. <div class="attendance-row"><div class="attendance-avatar">李</div><div class="attendance-info"><div class="attendance-name">李四</div><div class="attendance-role">搬运</div></div><div class="attendance-stat"><div class="hours overtime">10h</div><div class="label">原8h+加班2h</div></div></div>
  1676. <div class="attendance-row"><div class="attendance-avatar">王</div><div class="attendance-info"><div class="attendance-name">王五</div><div class="attendance-role">包装</div></div><div class="attendance-stat"><div class="hours">500件</div><div class="label">计件</div></div></div>
  1677. <div class="attendance-row"><div class="attendance-avatar">赵</div><div class="attendance-info"><div class="attendance-name">赵六</div><div class="attendance-role">搬运</div></div><div class="attendance-stat"><div class="hours">8h</div><div class="label">正常</div></div></div>
  1678. </div>
  1679. <div class="form-section" style="margin-top:16px;background:var(--primary-bg);border-color:var(--primary-light);">
  1680. <div style="font-size:14px;font-weight:700;margin-bottom:8px;">今日汇总</div>
  1681. <div class="form-row"><span class="label">总工时</span><span class="value">78h</span></div>
  1682. <div class="form-row"><span class="label">总件数</span><span class="value">500件</span></div>
  1683. <div class="form-row"><span class="label">预估费用</span><span class="value highlight">¥8,580</span></div>
  1684. </div>
  1685. </div>
  1686. <div class="sheet-footer">
  1687. <button class="btn btn-secondary btn-lg" style="flex:1;" onclick="showToast('语音录入模式')"><i class="ri-mic-line"></i> 语音录入</button>
  1688. <button class="btn btn-primary btn-lg" style="flex:1;" onclick="showToast('考勤已归档');closeAll();">确认归档</button>
  1689. </div>
  1690. </div>
  1691. <!-- ===== SIDE DRAWER: MESSAGES ===== -->
  1692. <div class="side-drawer" id="drawerMessage">
  1693. <div class="drawer-header"><div class="drawer-title"><i class="ri-notification-3-line" style="color:var(--primary);"></i> 消息与待办</div></div>
  1694. <div class="drawer-body">
  1695. <div class="drawer-section-title">待处理</div>
  1696. <div class="msg-item" onclick="closeAll();setTimeout(()=>openSheet('settlement'),350);">
  1697. <div class="msg-item-header"><span class="msg-type pending">待确认</span><span class="msg-time">2小时前</span></div>
  1698. <div class="msg-title">12月浦东仓库结算单</div>
  1699. <div class="msg-desc">¥50,400 · 共10人</div>
  1700. <button class="msg-action">去处理 <i class="ri-arrow-right-s-line"></i></button>
  1701. </div>
  1702. <div class="msg-item" onclick="closeAll();setTimeout(()=>openSheet('progress'),350);">
  1703. <div class="msg-item-header"><span class="msg-type error">异常</span><span class="msg-time">5小时前</span></div>
  1704. <div class="msg-title">王五实名核验失败</div>
  1705. <div class="msg-desc">光线不足导致人脸比对失败</div>
  1706. <button class="msg-action">查看原因 <i class="ri-arrow-right-s-line"></i></button>
  1707. </div>
  1708. <div class="msg-item">
  1709. <div class="msg-item-header"><span class="msg-type info">通知</span><span class="msg-time">1天前</span></div>
  1710. <div class="msg-title">批次 BATCH-001 登记进度更新</div>
  1711. <div class="msg-desc">7/10 人已完成登记</div>
  1712. </div>
  1713. <div class="drawer-section-title">已处理</div>
  1714. <div class="msg-item" style="opacity:0.6;">
  1715. <div class="msg-item-header"><span style="font-size:12px;font-weight:600;color:var(--success);">已确认</span><span class="msg-time">3天前</span></div>
  1716. <div class="msg-title">批次 BATCH-001 方案确认</div>
  1717. </div>
  1718. </div>
  1719. </div>
  1720. <!-- ===== SIDE DRAWER: PROFILE ===== -->
  1721. <div class="side-drawer" id="drawerProfile">
  1722. <div class="drawer-header" style="padding-bottom:0;border:none;"></div>
  1723. <div class="drawer-body">
  1724. <div class="profile-card">
  1725. <div class="profile-avatar-lg">张</div>
  1726. <div class="profile-name">某某科技有限公司</div>
  1727. <div class="profile-meta">91310000...</div>
  1728. <div class="profile-status-badge"><i class="ri-check-line"></i> 已认证</div>
  1729. </div>
  1730. <div class="drawer-section-title">消息与待办中心</div>
  1731. <div class="profile-menu-item" onclick="closeAll();setTimeout(()=>toggleDrawer('message'),350);">
  1732. <div class="profile-menu-icon" style="background:var(--warning-light);"><i class="ri-notification-3-line" style="color:var(--warning);"></i></div>
  1733. <div class="profile-menu-text"><div class="profile-menu-title">消息与待办中心</div><div class="profile-menu-desc">待确认 2 条</div></div>
  1734. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1735. </div>
  1736. <div class="profile-divider"></div>
  1737. <div class="drawer-section-title">智能偏好设置</div>
  1738. <div class="profile-menu-item" onclick="openConfig('workType')">
  1739. <div class="profile-menu-icon" style="background:var(--info-light);"><i class="ri-tools-line" style="color:var(--info);"></i></div>
  1740. <div class="profile-menu-text"><div class="profile-menu-title">常用工种与薪资基准</div></div>
  1741. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1742. </div>
  1743. <div class="profile-menu-item" onclick="openConfig('insurance')">
  1744. <div class="profile-menu-icon" style="background:var(--success-light);"><i class="ri-shield-check-line" style="color:var(--success);"></i></div>
  1745. <div class="profile-menu-text"><div class="profile-menu-title">默认保险方案偏好</div><div class="profile-menu-desc">已配置</div></div>
  1746. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1747. </div>
  1748. <div class="profile-menu-item" onclick="openConfig('payment')">
  1749. <div class="profile-menu-icon" style="background:var(--warning-light);"><i class="ri-calendar-check-line" style="color:var(--warning);"></i></div>
  1750. <div class="profile-menu-text"><div class="profile-menu-title">常规发薪日与结算周期</div></div>
  1751. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1752. </div>
  1753. <div class="profile-divider"></div>
  1754. <div class="drawer-section-title">财务与账户</div>
  1755. <div class="profile-menu-item">
  1756. <div class="profile-menu-icon" style="background:var(--danger-light);"><i class="ri-bank-card-line" style="color:var(--danger);"></i></div>
  1757. <div class="profile-menu-text"><div class="profile-menu-title">对公账户与打款通道</div></div>
  1758. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1759. </div>
  1760. <div class="profile-menu-item">
  1761. <div class="profile-menu-icon" style="background:var(--primary-bg);"><i class="ri-file-list-2-line" style="color:var(--primary);"></i></div>
  1762. <div class="profile-menu-text"><div class="profile-menu-title">企业开票抬头与税控</div></div>
  1763. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1764. </div>
  1765. <div class="profile-menu-item">
  1766. <div class="profile-menu-icon" style="background:var(--gray-100);"><i class="ri-wallet-3-line" style="color:var(--gray-600);"></i></div>
  1767. <div class="profile-menu-text"><div class="profile-menu-title">平台余额与充值管理</div></div>
  1768. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1769. </div>
  1770. <div class="profile-divider"></div>
  1771. <div class="drawer-section-title">合规与安全审计</div>
  1772. <div class="profile-menu-item">
  1773. <div class="profile-menu-icon" style="background:var(--primary-bg);"><i class="ri-file-paper-2-line" style="color:var(--primary);"></i></div>
  1774. <div class="profile-menu-text"><div class="profile-menu-title">历史合同与电子签章归档</div></div>
  1775. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1776. </div>
  1777. <div class="profile-menu-item">
  1778. <div class="profile-menu-icon" style="background:var(--info-light);"><i class="ri-search-eye-line" style="color:var(--info);"></i></div>
  1779. <div class="profile-menu-text"><div class="profile-menu-title">操作日志与合规证据链导出</div></div>
  1780. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1781. </div>
  1782. <div class="profile-menu-item">
  1783. <div class="profile-menu-icon" style="background:var(--success-light);"><i class="ri-notification-3-line" style="color:var(--success);"></i></div>
  1784. <div class="profile-menu-text"><div class="profile-menu-title">关键节点消息通知设置</div></div>
  1785. <div class="profile-menu-arrow"><i class="ri-arrow-right-s-line"></i></div>
  1786. </div>
  1787. <div class="profile-divider"></div>
  1788. <div class="drawer-section-title">系统设置与帮助</div>
  1789. <div style="display:flex;gap:8px;flex-wrap:wrap;">
  1790. <button class="btn btn-secondary btn-sm"><i class="ri-information-line"></i> 关于我们</button>
  1791. <button class="btn btn-secondary btn-sm"><i class="ri-question-line"></i> 常见问题</button>
  1792. <button class="btn btn-secondary btn-sm"><i class="ri-customer-service-2-line"></i> 联系客服</button>
  1793. </div>
  1794. <div style="margin-top:20px;padding-top:14px;border-top:1px solid var(--border-light);">
  1795. <button class="btn btn-secondary btn-lg btn-full" onclick="closeAll();setTimeout(()=>goTo('login'),350);" style="color:var(--danger);">
  1796. <i class="ri-logout-box-r-line"></i> 退出账号
  1797. </button>
  1798. </div>
  1799. </div>
  1800. </div>
  1801. <!-- ===== MODAL: CONFIRM ===== -->
  1802. <div class="modal-overlay" id="modalOverlay" onclick="closeModal()"></div>
  1803. <div class="modal" id="modalConfirm">
  1804. <div class="modal-body">
  1805. <div class="modal-icon success"><i class="ri-check-line"></i></div>
  1806. <div class="modal-title" id="modalTitle">确认选择方案A?</div>
  1807. <div class="modal-desc" id="modalDesc">合规优先 · 总支出 ¥12,800<br>确认后将生成批次二维码</div>
  1808. </div>
  1809. <div class="modal-footer">
  1810. <button class="modal-btn cancel" onclick="closeModal()">取消</button>
  1811. <button class="modal-btn confirm" id="modalConfirmBtn" onclick="confirmAction()">确认生成</button>
  1812. </div>
  1813. </div>
  1814. <!-- ===== MODAL: QR ===== -->
  1815. <div class="modal" id="modalQR" style="max-width:380px;">
  1816. <div class="modal-body" style="padding:20px;">
  1817. <div class="modal-title" style="margin-bottom:4px;">方案已确认</div>
  1818. <div style="font-size:13px;color:var(--muted);margin-bottom:12px;">浦东仓库搬运 BATCH-001</div>
  1819. <div class="qr-area">
  1820. <svg viewBox="0 0 100 100" fill="currentColor">
  1821. <rect x="5" y="5" width="25" height="25" rx="2"/>
  1822. <rect x="70" y="5" width="25" height="25" rx="2"/>
  1823. <rect x="5" y="70" width="25" height="25" rx="2"/>
  1824. <rect x="10" y="10" width="15" height="15" rx="1" fill="white"/>
  1825. <rect x="75" y="10" width="15" height="15" rx="1" fill="white"/>
  1826. <rect x="10" y="75" width="15" height="15" rx="1" fill="white"/>
  1827. <rect x="14" y="14" width="7" height="7" rx="0.5"/>
  1828. <rect x="79" y="14" width="7" height="7" rx="0.5"/>
  1829. <rect x="14" y="79" width="7" height="7" rx="0.5"/>
  1830. <rect x="35" y="5" width="8" height="8"/><rect x="48" y="5" width="8" height="8"/>
  1831. <rect x="35" y="18" width="8" height="8"/><rect x="60" y="35" width="8" height="8"/>
  1832. <rect x="35" y="48" width="8" height="8"/><rect x="48" y="35" width="8" height="8"/>
  1833. <rect x="35" y="60" width="8" height="8"/><rect x="60" y="60" width="8" height="8"/>
  1834. <rect x="75" y="48" width="8" height="8"/><rect x="87" y="48" width="8" height="8"/>
  1835. <rect x="75" y="70" width="8" height="8"/><rect x="87" y="70" width="8" height="8"/>
  1836. <rect x="75" y="87" width="8" height="8"/>
  1837. </svg>
  1838. </div>
  1839. <div style="font-size:13px;color:var(--muted);margin-bottom:12px;">分享给临时工扫码即可登记</div>
  1840. <div class="progress-bar-wrap" style="margin-bottom:12px;">
  1841. <div class="progress-label"><span class="text">登记进度</span><span class="count">7/10</span></div>
  1842. <div class="progress-track"><div class="progress-fill" style="width:70%;"></div></div>
  1843. </div>
  1844. <div class="qr-actions">
  1845. <button class="qr-action" onclick="showToast('已保存到相册')"><i class="ri-image-line"></i> 保存相册</button>
  1846. <button class="qr-action" onclick="showToast('已分享')"><i class="ri-share-line"></i> 分享好友</button>
  1847. <button class="qr-action" onclick="showToast('已复制链接')"><i class="ri-links-line"></i> 复制链接</button>
  1848. <button class="qr-action" onclick="closeModal();setTimeout(()=>openSheet('progress'),300);"><i class="ri-line-chart-line"></i> 查看进度</button>
  1849. </div>
  1850. </div>
  1851. </div>
  1852. <!-- ===== MODAL: PAYMENT ===== -->
  1853. <div class="modal" id="modalPayment" style="max-width:340px;">
  1854. <div class="modal-body">
  1855. <div class="modal-icon warning"><i class="ri-lock-line"></i></div>
  1856. <div class="modal-title">资金安全确认</div>
  1857. <div class="modal-desc">您即将向 10 位临时工<br>支付 <strong>¥50,400</strong><br><br>请验证身份以完成打款</div>
  1858. </div>
  1859. <div class="modal-footer" style="flex-direction:column;">
  1860. <button class="modal-btn confirm" onclick="showPaySuccess()" style="width:100%;">微信支付密码验证</button>
  1861. <button class="modal-btn cancel" onclick="closeModal()" style="width:100%;">取消</button>
  1862. </div>
  1863. </div>
  1864. <!-- ===== MODAL: PAY SUCCESS ===== -->
  1865. <div class="modal" id="modalPaySuccess" style="max-width:340px;">
  1866. <div class="modal-body">
  1867. <div class="modal-icon success" style="animation:countUp 0.4s ease both;"><i class="ri-check-double-line"></i></div>
  1868. <div class="modal-title">支付成功!</div>
  1869. <div class="modal-desc">¥50,400 已发起打款<br>预计2小时内到账</div>
  1870. </div>
  1871. <div class="modal-footer">
  1872. <button class="modal-btn cancel" onclick="closeModal();closeAll();" style="flex:1;">关闭</button>
  1873. <button class="modal-btn confirm" onclick="showToast('已下载凭证');closeModal();closeAll();" style="flex:1;">下载凭证</button>
  1874. </div>
  1875. </div>
  1876. <!-- ===== CONFIG OVERLAY + SHEET ===== -->
  1877. <div class="config-overlay" id="configOverlay" onclick="closeConfig()"></div>
  1878. <div class="config-sheet" id="configSheet">
  1879. <div class="sheet-handle"></div>
  1880. <div class="sheet-header">
  1881. <div class="sheet-title" id="configTitle"><i class="ri-shield-check-line" style="color:var(--primary);"></i> 保险方案偏好</div>
  1882. <button class="btn btn-ghost btn-sm" onclick="closeConfig()" style="font-size:20px;"><i class="ri-close-line"></i></button>
  1883. </div>
  1884. <div class="sheet-source" id="configSource"><i class="ri-links-line"></i> 来自:企业管理中枢</div>
  1885. <div class="sheet-body" id="configBody">
  1886. <div id="configMessages"></div>
  1887. </div>
  1888. <div class="sheet-footer" style="border-top:1px solid var(--border-light);">
  1889. <div style="display:flex;gap:8px;width:100%;">
  1890. <input class="input-field" id="configInput" type="text" placeholder="描述您的配置需求..." style="flex:1;" onkeydown="if(event.key==='Enter')sendConfigMsg()">
  1891. <button class="icon-btn send-btn active" onclick="sendConfigMsg()" style="width:44px;height:44px;"><i class="ri-send-plane-fill"></i></button>
  1892. </div>
  1893. </div>
  1894. </div>
  1895. <!-- ===== TOAST ===== -->
  1896. <div id="toast"></div>
  1897. </div>
  1898. <script>
  1899. // ===== STATE =====
  1900. let currentSheet = null;
  1901. let confirmCallback = null;
  1902. // ===== PAGES =====
  1903. function goTo(page) {
  1904. document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
  1905. const navItems = document.querySelectorAll('.bottom-nav-item');
  1906. navItems.forEach(n => n.classList.remove('active'));
  1907. const pageMap = { login:'pageLogin', chat:'pageChat', worker:'pageWorker', wallet:'pageWallet', profile:'pageProfile' };
  1908. const el = document.getElementById(pageMap[page]);
  1909. if (el) el.classList.add('active');
  1910. navItems.forEach(n => { if(n.dataset.page === page) n.classList.add('active'); });
  1911. const bn = document.getElementById('bottomNav');
  1912. if (page === 'login' || page === 'chat') { bn.style.display = 'none'; }
  1913. else { bn.style.display = 'flex'; }
  1914. if (page === 'chat') initChat();
  1915. if (page === 'wallet') animateSalary();
  1916. closeAll();
  1917. }
  1918. function animateSalary() {
  1919. const el = document.getElementById('salaryAmount');
  1920. if (!el) return;
  1921. const target = 3500;
  1922. const duration = 1200;
  1923. const start = performance.now();
  1924. el.textContent = '¥0';
  1925. function step(ts) {
  1926. const progress = Math.min((ts - start) / duration, 1);
  1927. const eased = 1 - Math.pow(1 - progress, 3);
  1928. const current = Math.round(eased * target);
  1929. el.textContent = '¥' + current.toLocaleString();
  1930. if (progress < 1) requestAnimationFrame(step);
  1931. }
  1932. requestAnimationFrame(step);
  1933. }
  1934. // ===== CHAT SIDEBAR =====
  1935. function toggleSidebar() {
  1936. document.getElementById('chatSidebar').classList.toggle('open');
  1937. }
  1938. function switchChat(el, type) {
  1939. document.querySelectorAll('.chat-item').forEach(i => i.classList.remove('active'));
  1940. el.classList.add('active');
  1941. document.getElementById('chatSidebar').classList.remove('open');
  1942. loadChatHistory(type);
  1943. }
  1944. const chatData = {
  1945. employment: [
  1946. { role:'ai', text:'greeting' },
  1947. { role:'ai', text:'report' },
  1948. { role:'ai', text:'draft' },
  1949. { role:'user', text:'招10个搬运工,浦东仓库,2天' },
  1950. { role:'ai', text:'summary1' },
  1951. { role:'ai', text:'summary2' },
  1952. ],
  1953. knowledge: [
  1954. { role:'ai', text:'我可以为您解答灵活用工政策法规、税务处理、合同管理、社保保险、用工风险等方面的问题。请告诉我您想了解哪方面的内容?' },
  1955. { role:'ai', text:'knowledge_actions' },
  1956. ],
  1957. order: [
  1958. { role:'ai', text:'当前订单状态:' },
  1959. { role:'ai', text:'orders' },
  1960. ],
  1961. cost: [
  1962. { role:'ai', text:'请告诉我用工人数、工作天数和日薪标准,我来帮您精准测算成本。例如:"10个人,工作2天,日薪500元"' },
  1963. ],
  1964. attendance: [
  1965. { role:'ai', text:'请用自然语言描述今天的考勤情况,例如:"今天张三请假,李四加班了2小时,王五计件做了500个"。我会自动匹配当前批次并生成考勤卡片。' },
  1966. ],
  1967. emergency: [
  1968. { role:'ai', text:'当发生紧急事件时,请描述事件情况,我会生成处理指南并帮您一键生成保险报案草稿。例如:"有工人搬东西砸到脚了,现在去医院"' },
  1969. ],
  1970. };
  1971. let currentChatType = 'employment';
  1972. function initChat() {
  1973. loadChatHistory(currentChatType);
  1974. }
  1975. function loadChatHistory(type) {
  1976. currentChatType = type;
  1977. const area = document.getElementById('chatArea');
  1978. area.innerHTML = '';
  1979. const msgs = chatData[type] || [];
  1980. msgs.forEach(m => addChatMsg(m.role, m.text));
  1981. area.scrollTop = area.scrollHeight;
  1982. }
  1983. function addChatMsg(role, text) {
  1984. const area = document.getElementById('chatArea');
  1985. const div = document.createElement('div');
  1986. div.className = `chat-msg ${role}`;
  1987. if (role === 'ai') {
  1988. let content = '';
  1989. if (text === 'greeting') {
  1990. content = `<p>老板早上好!为您汇报昨日进度:</p>`;
  1991. } else if (text === 'report') {
  1992. content = `<div class="biz-card report-card" onclick="openSheet('progress')">
  1993. <div class="biz-card-header"><i class="ri-bar-chart-line" style="color:var(--primary);"></i> 今日汇报</div>
  1994. <div class="biz-card-row"><span>1. 浦东仓库</span><span class="val">8/10 人已登记</span></div>
  1995. <div class="biz-card-row"><span>2. 王五实名失败</span><span class="val" style="color:var(--danger);">已自动提醒</span></div>
  1996. <div class="biz-card-row"><span>3. 结算单待确认</span><span class="val">¥12,800</span></div>
  1997. <div class="biz-card-actions">
  1998. <button class="biz-btn" onclick="event.stopPropagation();showToast('已发送催办')"><i class="ri-notification-3-line"></i> 一键催办</button>
  1999. <button class="biz-btn" onclick="event.stopPropagation();openSheet('progress')"><i class="ri-line-chart-line"></i> 查看进度</button>
  2000. </div>
  2001. </div>
  2002. <div class="quick-actions" style="margin-top:10px;">
  2003. <button class="quick-action" onclick="triggerAI('发布需求')"><div class="quick-action-icon" style="background:var(--warning-light);"><i class="ri-add-line" style="color:var(--warning);"></i></div><span class="quick-action-label">发布需求</span></button>
  2004. <button class="quick-action" onclick="openSheet('cost')"><div class="quick-action-icon" style="background:var(--success-light);"><i class="ri-money-cny-circle-line" style="color:var(--success);"></i></div><span class="quick-action-label">成本测算</span></button>
  2005. <button class="quick-action" onclick="openSheet('progress')"><div class="quick-action-icon" style="background:var(--info-light);"><i class="ri-line-chart-line" style="color:var(--info);"></i></div><span class="quick-action-label">进度总览</span></button>
  2006. <button class="quick-action" onclick="openSheet('settlement')"><div class="quick-action-icon" style="background:var(--danger-light);"><i class="ri-bank-card-line" style="color:var(--danger);"></i></div><span class="quick-action-label">历史订单</span></button>
  2007. </div>`;
  2008. } else if (text === 'draft') {
  2009. content = `<div class="biz-card draft-card" onclick="openSheet('draft')">
  2010. <div class="biz-card-header"><i class="ri-file-text-line" style="color:var(--warning);"></i> 用工草稿</div>
  2011. <div class="biz-card-row"><span>岗位类型</span><span class="val">搬运工</span></div>
  2012. <div class="biz-card-row"><span>工作地点</span><span class="val">浦东新区</span></div>
  2013. <div class="biz-card-row"><span>用工人数</span><span class="val">10人 × 2天</span></div>
  2014. <div class="draft-price">¥12,800 <small>预估总价</small></div>
  2015. <div class="biz-card-actions">
  2016. <button class="biz-btn primary" onclick="event.stopPropagation();openSheet('draft')"><i class="ri-eye-line"></i> 查看详情/修改</button>
  2017. </div>
  2018. </div>`;
  2019. } else if (text === 'orders') {
  2020. content = `<div class="biz-card" style="margin-bottom:8px;">
  2021. <div class="biz-card-header"><i class="ri-file-list-line" style="color:var(--primary);"></i> 订单 #2024-001 · 活动执行</div>
  2022. <div class="biz-card-row"><span>状态</span><span class="val" style="color:var(--success);">进行中</span></div>
  2023. <div class="biz-card-row"><span>人数/时间</span><span class="val">10人 · 01-20至21</span></div>
  2024. <div class="biz-card-row"><span>已登记</span><span class="val">7/10人</span></div>
  2025. </div>
  2026. <div class="biz-card" style="margin-bottom:8px;">
  2027. <div class="biz-card-header"><i class="ri-file-list-line" style="color:var(--warning);"></i> 订单 #2024-002 · 促销推广</div>
  2028. <div class="biz-card-row"><span>状态</span><span class="val" style="color:var(--warning);">待确认</span></div>
  2029. <div class="biz-card-row"><span>人数/时间</span><span class="val">5人 · 01-25至26</span></div>
  2030. </div>`;
  2031. } else if (text === 'summary1') {
  2032. content = `<div class="summary-bubble" onclick="openSheet('draft')"><i class="ri-check-line"></i><span><span class="text">方案A已确认</span> · 合规优先 · ¥12,800</span></div>`;
  2033. div.innerHTML = `<div class="chat-avatar ai" style="visibility:hidden;"></div><div class="chat-bubble">${content}</div>`;
  2034. area.appendChild(div);
  2035. return;
  2036. } else if (text === 'summary2') {
  2037. content = `<div class="summary-bubble" onclick="openSheet('settlement')"><i class="ri-check-line"></i><span><span class="text">结算已支付</span> · ¥50,400 · BATCH-001</span></div>`;
  2038. div.innerHTML = `<div class="chat-avatar ai" style="visibility:hidden;"></div><div class="chat-bubble">${content}</div>`;
  2039. area.appendChild(div);
  2040. return;
  2041. } else if (text === 'knowledge_actions') {
  2042. content = `<div class="quick-actions" style="margin-top:10px;">
  2043. <button class="quick-action" onclick="triggerAI('政策法规')"><div class="quick-action-icon" style="background:var(--info-light);"><i class="ri-government-line" style="color:var(--info);"></i></div><span class="quick-action-label">政策法规</span></button>
  2044. <button class="quick-action" onclick="triggerAI('税务处理')"><div class="quick-action-icon" style="background:var(--warning-light);"><i class="ri-money-cny-circle-line" style="color:var(--warning);"></i></div><span class="quick-action-label">税务处理</span></button>
  2045. <button class="quick-action" onclick="triggerAI('合同管理')"><div class="quick-action-icon" style="background:var(--success-light);"><i class="ri-file-text-line" style="color:var(--success);"></i></div><span class="quick-action-label">合同管理</span></button>
  2046. <button class="quick-action" onclick="triggerAI('社保保险')"><div class="quick-action-icon" style="background:var(--danger-light);"><i class="ri-shield-check-line" style="color:var(--danger);"></i></div><span class="quick-action-label">社保保险</span></button>
  2047. </div>`;
  2048. } else {
  2049. content = `<p>${text}</p>`;
  2050. }
  2051. div.innerHTML = `<div class="chat-avatar ai"><i class="ri-robot-2-line"></i></div><div class="chat-bubble">${content}</div>`;
  2052. } else {
  2053. div.innerHTML = `<div class="chat-avatar user">张</div><div class="chat-bubble">${text}</div>`;
  2054. }
  2055. area.appendChild(div);
  2056. }
  2057. function startNewChat() {
  2058. document.getElementById('chatSidebar').classList.remove('open');
  2059. loadChatHistory('employment');
  2060. showToast('已开启新对话');
  2061. }
  2062. // ===== INPUT =====
  2063. function toggleSendBtn() {
  2064. const v = document.getElementById('chatInput').value.trim();
  2065. document.getElementById('sendBtn').classList.toggle('active', v.length > 0);
  2066. }
  2067. function sendMsg() {
  2068. const input = document.getElementById('chatInput');
  2069. const text = input.value.trim();
  2070. if (!text) return;
  2071. addChatMsg('user', text);
  2072. input.value = '';
  2073. toggleSendBtn();
  2074. const area = document.getElementById('chatArea');
  2075. const thinking = document.createElement('div');
  2076. thinking.className = 'thinking';
  2077. thinking.innerHTML = `<div class="chat-avatar ai"><i class="ri-robot-2-line"></i></div><div class="thinking-dots"><span></span><span></span><span></span></div>`;
  2078. area.appendChild(thinking);
  2079. area.scrollTop = area.scrollHeight;
  2080. setTimeout(() => {
  2081. thinking.remove();
  2082. if (text.includes('招') || text.includes('搬运') || text.includes('临时工')) {
  2083. addChatMsg('ai', '好的,已为您分析需求。正在生成用工草稿...');
  2084. setTimeout(() => {
  2085. addChatMsg('ai', 'draft');
  2086. area.scrollTop = area.scrollHeight;
  2087. }, 600);
  2088. } else {
  2089. addChatMsg('ai', '我理解您的问题,我可以帮您:发布用工需求、测算成本、查看进度、管理订单。请告诉我您具体想做什么?');
  2090. }
  2091. area.scrollTop = area.scrollHeight;
  2092. }, 1200);
  2093. }
  2094. function triggerAI(msg) {
  2095. document.getElementById('chatInput').value = msg;
  2096. sendMsg();
  2097. }
  2098. // ===== BOTTOM SHEETS =====
  2099. function openSheet(name) {
  2100. closeAll();
  2101. const map = { draft:'sheetDraft', cost:'sheetCost', progress:'sheetProgress', settlement:'sheetSettlement', attendant:'sheetAttendant' };
  2102. const el = document.getElementById(map[name]);
  2103. if (el) {
  2104. setTimeout(() => {
  2105. document.getElementById('overlay').classList.add('active');
  2106. el.classList.add('active');
  2107. currentSheet = el;
  2108. }, 50);
  2109. }
  2110. }
  2111. // ===== SIDE DRAWERS =====
  2112. function toggleDrawer(name) {
  2113. closeAll();
  2114. const map = { message:'drawerMessage', profile:'drawerProfile' };
  2115. const el = document.getElementById(map[name]);
  2116. if (el) {
  2117. setTimeout(() => {
  2118. document.getElementById('overlay').classList.add('active');
  2119. el.classList.add('active');
  2120. }, 50);
  2121. }
  2122. }
  2123. function closeAll() {
  2124. document.getElementById('overlay').classList.remove('active');
  2125. document.querySelectorAll('.bottom-sheet, .side-drawer').forEach(el => el.classList.remove('active'));
  2126. currentSheet = null;
  2127. }
  2128. // ===== MODALS =====
  2129. function openModal(id) {
  2130. document.getElementById('modalOverlay').classList.add('active');
  2131. document.getElementById(id).classList.add('active');
  2132. }
  2133. function closeModal() {
  2134. document.getElementById('modalOverlay').classList.remove('active');
  2135. document.querySelectorAll('.modal').forEach(el => el.classList.remove('active'));
  2136. }
  2137. // ===== DRAFT CONFIRM =====
  2138. function confirmDraft() {
  2139. closeAll();
  2140. setTimeout(() => {
  2141. document.getElementById('modalTitle').textContent = '确认选择方案A?';
  2142. document.getElementById('modalDesc').innerHTML = '合规优先 · 总支出 ¥12,800<br>确认后将生成批次二维码';
  2143. confirmCallback = () => { closeModal(); setTimeout(()=>{document.getElementById('modalOverlay').classList.add('active');document.getElementById('modalQR').classList.add('active');},300); };
  2144. openModal('modalConfirm');
  2145. }, 400);
  2146. }
  2147. function confirmCost() {
  2148. closeAll();
  2149. setTimeout(() => {
  2150. document.getElementById('modalTitle').textContent = '确认选择方案A?';
  2151. document.getElementById('modalDesc').innerHTML = '合规优先 · 总支出 ¥12,800<br>确认后将生成批次二维码';
  2152. confirmCallback = () => { closeModal(); setTimeout(()=>{document.getElementById('modalOverlay').classList.add('active');document.getElementById('modalQR').classList.add('active');},300); };
  2153. openModal('modalConfirm');
  2154. }, 400);
  2155. }
  2156. function confirmAction() { if(confirmCallback) confirmCallback(); }
  2157. function showPayment() { closeModal(); setTimeout(()=>{document.getElementById('modalOverlay').classList.add('active');document.getElementById('modalPayment').classList.add('active');},300); }
  2158. function showPaySuccess() { closeModal(); setTimeout(()=>{document.getElementById('modalOverlay').classList.add('active');document.getElementById('modalPaySuccess').classList.add('active');},300); }
  2159. // ===== DRAFT NL EDIT =====
  2160. function toggleDraftConfirm() {
  2161. const v = document.getElementById('draftNlInput').value.trim();
  2162. document.getElementById('draftConfirmBtn').style.display = v ? 'inline-flex' : 'none';
  2163. }
  2164. function confirmNlEdit() {
  2165. showToast('修改已确认');
  2166. document.getElementById('draftNlInput').value = '';
  2167. toggleDraftConfirm();
  2168. }
  2169. // ===== CONFIG DIALOG =====
  2170. const configData = {
  2171. workType: { title:'常用工种与薪资基准', welcome:'请告诉我您常用的工种和薪资基准,例如:"活动执行类日薪500-600元,搬运工400-500元"' },
  2172. insurance: { title:'默认保险方案偏好', welcome:'请告诉我您的保险偏好,例如:"高空作业买高档雇主险,普通搬运买基础意外险"' },
  2173. payment: { title:'常规发薪日与结算周期', welcome:'请告诉我您的发薪日和结算周期,例如:"每月15号发薪,用工结束后3个工作日内结算"' },
  2174. };
  2175. function openConfig(type) {
  2176. // Keep profile drawer open behind the config sheet
  2177. const cfg = configData[type];
  2178. document.getElementById('configTitle').innerHTML = `<i class="ri-shield-check-line" style="color:var(--primary);"></i> ${cfg.title}`;
  2179. document.getElementById('configSource').innerHTML = `<i class="ri-links-line"></i> 来自:企业管理中枢`;
  2180. const msgs = document.getElementById('configMessages');
  2181. msgs.innerHTML = '';
  2182. addConfigMsg('ai', cfg.welcome);
  2183. document.getElementById('configOverlay').classList.add('active');
  2184. document.getElementById('configSheet').classList.add('active');
  2185. document.getElementById('configInput').value = '';
  2186. }
  2187. function closeConfig() {
  2188. document.getElementById('configOverlay').classList.remove('active');
  2189. document.getElementById('configSheet').classList.remove('active');
  2190. }
  2191. function sendConfigMsg() {
  2192. const input = document.getElementById('configInput');
  2193. const text = input.value.trim();
  2194. if (!text) return;
  2195. addConfigMsg('user', text);
  2196. input.value = '';
  2197. setTimeout(() => {
  2198. addConfigMsg('ai', `已解析您的配置需求。以下是识别到的规则:\n\n"${text}"\n\n请确认此配置,确认后将应用于后续所有用工草稿。`);
  2199. }, 800);
  2200. }
  2201. function addConfigMsg(role, text) {
  2202. const msgs = document.getElementById('configMessages');
  2203. const div = document.createElement('div');
  2204. div.className = `chat-msg ${role}`;
  2205. if (role === 'ai') {
  2206. div.innerHTML = `<div class="chat-avatar ai" style="width:28px;height:28px;"><i class="ri-robot-2-line" style="font-size:14px;"></i></div><div class="chat-bubble" style="font-size:14px;padding:10px 14px;white-space:pre-line;">${text}</div>`;
  2207. } else {
  2208. div.innerHTML = `<div class="chat-avatar user" style="width:28px;height:28px;font-size:11px;">张</div><div class="chat-bubble" style="font-size:14px;padding:10px 14px;">${text}</div>`;
  2209. }
  2210. msgs.appendChild(div);
  2211. document.getElementById('configBody').scrollTop = document.getElementById('configBody').scrollHeight;
  2212. }
  2213. // ===== TOAST =====
  2214. function showToast(msg) {
  2215. const t = document.getElementById('toast');
  2216. t.textContent = msg;
  2217. t.style.opacity = '1';
  2218. t.style.transform = 'translateX(-50%) translateY(0)';
  2219. setTimeout(() => { t.style.opacity = '0'; t.style.transform = 'translateX(-50%) translateY(-20px)'; }, 2000);
  2220. }
  2221. // ===== SWIPE TO CLOSE =====
  2222. let touchStartY = 0;
  2223. document.querySelectorAll('.sheet-handle').forEach(h => {
  2224. h.addEventListener('touchstart', e => { touchStartY = e.touches[0].clientY; }, {passive:true});
  2225. h.addEventListener('touchmove', e => {
  2226. if (e.touches[0].clientY - touchStartY > 60) closeAll();
  2227. }, {passive:true});
  2228. });
  2229. // ===== OVERLAY CLICK =====
  2230. document.getElementById('overlay').addEventListener('click', closeAll);
  2231. // ===== INIT =====
  2232. goTo('login');
  2233. // ===== LOGIN TAB SWITCH =====
  2234. function switchLoginTab(tab) {
  2235. const entBtn = document.getElementById('loginTabEnterprise');
  2236. const workerBtn = document.getElementById('loginTabWorker');
  2237. const entForm = document.getElementById('loginFormEnterprise');
  2238. const workerForm = document.getElementById('loginFormWorker');
  2239. if (tab === 'enterprise') {
  2240. entBtn.style.background = 'var(--primary)';
  2241. entBtn.style.color = 'white';
  2242. entBtn.style.borderColor = 'var(--primary)';
  2243. workerBtn.style.background = 'var(--surface)';
  2244. workerBtn.style.color = 'var(--gray-600)';
  2245. workerBtn.style.borderColor = 'var(--border)';
  2246. entForm.style.display = 'block';
  2247. workerForm.style.display = 'none';
  2248. } else {
  2249. workerBtn.style.background = 'var(--primary)';
  2250. workerBtn.style.color = 'white';
  2251. workerBtn.style.borderColor = 'var(--primary)';
  2252. entBtn.style.background = 'var(--surface)';
  2253. entBtn.style.color = 'var(--gray-600)';
  2254. entBtn.style.borderColor = 'var(--border)';
  2255. workerForm.style.display = 'block';
  2256. entForm.style.display = 'none';
  2257. }
  2258. }
  2259. </script>
  2260. </body>
  2261. </html>