prototype.html 82 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  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" />
  6. <title>医梦AI · OKR绩效 — 完整设计原型</title>
  7. <style>
  8. /* ═══════════════════════════════════════════════════════════════════
  9. Cohere-inspired tokens · 医梦AI (智慧医疗 OKR)
  10. Brand: 深靛蓝 #2b1f99 · 青 #3ad4d8
  11. ═══════════════════════════════════════════════════════════════ */
  12. :root {
  13. --bg: #ffffff;
  14. --surface: #ffffff;
  15. --surface-alt: #f7f7f8;
  16. --dark: #2b1f99;
  17. --dark-surface: #1d166b;
  18. --dark-deeper: #120d4a;
  19. --fg: #17171c;
  20. --fg-2: #616161;
  21. --muted: #93939f;
  22. --meta: #b0b0b8;
  23. --on-dark: #ffffff;
  24. --accent: #3ad4d8;
  25. --accent-hover: #17a9ad;
  26. --accent-soft: rgba(58,212,216,0.10);
  27. --accent-glow: rgba(58,212,216,0.18);
  28. --accent-hover-bg: rgba(58,212,216,0.06);
  29. --accent-micro: rgba(58,212,216,0.035);
  30. --success: #2e9d65;
  31. --warn: #c98219;
  32. --danger: #c94a4a;
  33. --info: #4c6f91;
  34. --orange: #f59e0b;
  35. --orange-bg: rgba(245,158,11,0.10);
  36. --orange-text: #b45309;
  37. --orange-border: rgba(245,158,11,0.25);
  38. --red: #dc2626;
  39. --red-bg: rgba(220,38,38,0.08);
  40. --red-text: #b91c1c;
  41. --red-border: rgba(220,38,38,0.20);
  42. --green-bg: rgba(46,157,101,0.08);
  43. --green-text: #1e6b3e;
  44. --indigo-soft: rgba(43,31,153,0.07);
  45. --indigo-border: rgba(43,31,153,0.18);
  46. --indigo-text: #1d166b;
  47. --border: #e5e5e9;
  48. --border-light: #f0f0f3;
  49. --border-soft: rgba(0,0,0,0.05);
  50. --font-display: 'Space Grotesk', -apple-system, 'Segoe UI', sans-serif;
  51. --font-body: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', 'Segoe UI', system-ui, sans-serif;
  52. --font-mono: 'SF Mono', 'JetBrains Mono', 'Menlo', ui-monospace, monospace;
  53. --fs-hero: clamp(48px,6vw,72px);
  54. --fs-h1: clamp(32px,3.8vw,48px);
  55. --fs-h2: 28px;
  56. --fs-h3: 20px;
  57. --fs-lead: 17px;
  58. --fs-body: 15px;
  59. --fs-sm: 13px;
  60. --fs-xs: 11px;
  61. --fs-num: clamp(40px,5vw,56px);
  62. --gap-xs: 6px;
  63. --gap-sm: 12px;
  64. --gap-md: 20px;
  65. --gap-lg: 32px;
  66. --gap-xl: 56px;
  67. --gap-2xl: 96px;
  68. --radius-xs: 4px;
  69. --radius-sm: 8px;
  70. --radius-md: 16px;
  71. --radius-lg: 22px;
  72. --radius-pill: 9999px;
  73. --container: 1120px;
  74. --gutter: 28px;
  75. --sidebar-w: 240px;
  76. }
  77. *, *::before, *::after { box-sizing: border-box; margin: 0; }
  78. html { font-size: var(--fs-body); line-height: 1.5; -webkit-font-smoothing: antialiased; }
  79. body { font-family: var(--font-body); color: var(--fg); background: var(--bg); }
  80. /* ─── App shell ──────────────────────────────────────────────── */
  81. .app { display: flex; height: 100vh; overflow: hidden; }
  82. .sidebar {
  83. width: var(--sidebar-w); min-width: var(--sidebar-w);
  84. background: var(--surface); border-right: 1px solid var(--border);
  85. display: flex; flex-direction: column; overflow-y: auto;
  86. }
  87. .sidebar-brand {
  88. padding: 20px 20px 16px; font-family: var(--font-display);
  89. font-size: 18px; font-weight: 600; color: var(--dark);
  90. border-bottom: 1px solid var(--border-light); letter-spacing: -0.3px;
  91. }
  92. .sidebar-brand span { color: var(--accent); }
  93. .nav-module { border-bottom: 1px solid var(--border-light); padding: 8px 0; }
  94. .nav-module__header {
  95. display: flex; align-items: center; gap: 8px; padding: 10px 20px;
  96. font-size: var(--fs-sm); font-weight: 600; color: var(--muted);
  97. cursor: pointer; user-select: none; letter-spacing: 0.5px; text-transform: uppercase;
  98. transition: color .15s;
  99. }
  100. .nav-module__header:hover { color: var(--fg-2); }
  101. .nav-module__arrow { font-size: 10px; transition: transform .2s; margin-left: auto; }
  102. .nav-module--collapsed .nav-module__arrow { transform: rotate(-90deg); }
  103. .nav-module--collapsed .nav-item { display: none; }
  104. .nav-item {
  105. display: flex; align-items: center; gap: 10px; padding: 9px 20px 9px 32px;
  106. font-size: 14px; color: var(--fg-2); cursor: pointer;
  107. border-radius: 0; transition: background .12s, color .12s;
  108. }
  109. .nav-item:hover { background: var(--accent-hover-bg); color: var(--fg); }
  110. .nav-item--active { background: var(--accent-soft); color: var(--dark); font-weight: 600;
  111. box-shadow: inset 3px 0 0 var(--accent); }
  112. .nav-item__icon { width: 18px; height: 18px; display: flex; align-items: center; justify-content: center;
  113. font-size: 13px; flex-shrink: 0; }
  114. .nav-item__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
  115. margin-left: auto; }
  116. .main {
  117. flex: 1; overflow-y: auto; background: var(--surface-alt);
  118. display: flex; flex-direction: column;
  119. }
  120. .page-panel { display: none; padding: var(--gap-lg); flex: 1; }
  121. .page-panel--active { display: block; }
  122. /* ─── Top bar ────────────────────────────────────────────────── */
  123. .topbar {
  124. display: flex; align-items: center; justify-content: space-between;
  125. padding: 0 var(--gap-lg); height: 56px; background: var(--surface);
  126. border-bottom: 1px solid var(--border-light); flex-shrink: 0;
  127. }
  128. .topbar__left { display: flex; align-items: center; gap: var(--gap-sm); }
  129. .topbar__title { font-size: var(--fs-h3); font-weight: 600; color: var(--fg); letter-spacing: -0.3px; }
  130. .topbar__actions { display: flex; align-items: center; gap: var(--gap-sm); }
  131. .topbar__avatar {
  132. width: 32px; height: 32px; border-radius: 50%; background: var(--accent);
  133. color: var(--dark); display: flex; align-items: center; justify-content: center;
  134. font-size: 13px; font-weight: 700; cursor: pointer;
  135. }
  136. /* ─── Common components ──────────────────────────────────────── */
  137. .s-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--gap-md); }
  138. .s-head__left h2 { font-size: var(--fs-h2); font-weight: 600; letter-spacing: -0.5px; color: var(--fg); }
  139. .s-head__left p { font-size: var(--fs-sm); color: var(--muted); margin-top: 2px; }
  140. .card {
  141. background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  142. padding: var(--gap-md); transition: box-shadow .15s, border-color .15s;
  143. }
  144. .card:hover { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
  145. .card--flat { border-radius: var(--radius-sm); }
  146. .card--lg { border-radius: var(--radius-lg); }
  147. /* Buttons */
  148. .btn {
  149. display: inline-flex; align-items: center; gap: 6px; border: none; cursor: pointer;
  150. font-family: var(--font-body); font-size: 14px; font-weight: 500;
  151. padding: 10px 20px; border-radius: var(--radius-pill); transition: all .15s;
  152. }
  153. .btn-primary { background: var(--accent); color: var(--dark); }
  154. .btn-primary:hover { background: var(--accent-hover); box-shadow: 0 0 0 3px var(--accent-glow); }
  155. .btn-outline { background: transparent; border: 1px solid var(--border); color: var(--fg-2); }
  156. .btn-outline:hover { border-color: var(--accent); color: var(--accent-hover); background: var(--accent-hover-bg); }
  157. .btn-sm { padding: 6px 14px; font-size: var(--fs-sm); }
  158. .btn-dark { background: var(--dark); color: var(--on-dark); }
  159. .btn-dark:hover { background: var(--dark-surface); }
  160. .btn-ghost { background: transparent; color: var(--fg-2); padding: 8px 12px; }
  161. .btn-ghost:hover { background: var(--accent-hover-bg); color: var(--fg); }
  162. .btn-danger { background: var(--red-bg); color: var(--red-text); }
  163. .btn-danger:hover { background: var(--red); color: #fff; }
  164. /* Tags / Badges */
  165. .tag {
  166. display: inline-flex; align-items: center; gap: 4px;
  167. font-size: var(--fs-xs); font-weight: 500; padding: 3px 10px;
  168. border-radius: var(--radius-pill); white-space: nowrap;
  169. }
  170. .tag-accent { background: var(--accent-soft); color: var(--accent-hover); }
  171. .tag-warn { background: var(--orange-bg); color: var(--orange-text); }
  172. .tag-danger { background: var(--red-bg); color: var(--red-text); }
  173. .tag-success { background: var(--green-bg); color: var(--green-text); }
  174. .tag-indigo { background: var(--indigo-soft); color: var(--indigo-text); }
  175. .tag-muted { background: var(--surface-alt); color: var(--muted); }
  176. /* Progress bar */
  177. .prog { height: 8px; background: var(--border-light); border-radius: var(--radius-pill); overflow: hidden; }
  178. .prog__fill { height: 100%; border-radius: var(--radius-pill); transition: width .4s; }
  179. .prog__fill--accent { background: var(--accent); }
  180. .prog__fill--indigo { background: var(--dark); }
  181. .prog__fill--orange { background: var(--orange); }
  182. .prog__fill--red { background: var(--red); }
  183. .prog__fill--green { background: var(--success); }
  184. /* Stat card */
  185. .stat-card {
  186. background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  187. padding: var(--gap-md); transition: border-color .15s, box-shadow .15s;
  188. }
  189. .stat-card:hover { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
  190. .stat-card__top { height: 4px; margin: calc(-1 * var(--gap-md)) calc(-1 * var(--gap-md)) var(--gap-sm); border-radius: var(--radius-md) var(--radius-md) 0 0; }
  191. .stat-card__top--accent { background: var(--accent); }
  192. .stat-card__top--indigo { background: var(--dark); }
  193. .stat-card__top--orange { background: var(--orange); }
  194. .stat-card__top--red { background: var(--red); }
  195. .stat-card__top--green { background: var(--success); }
  196. .stat-card__num { font-family: var(--font-display); font-size: var(--fs-num); font-weight: 700; line-height: 1; color: var(--fg); }
  197. .stat-card__label { font-size: var(--fs-sm); color: var(--muted); margin-top: 4px; }
  198. /* Metric bar */
  199. .m-bar { display: flex; align-items: center; gap: var(--gap-sm); }
  200. .m-bar__label { font-size: var(--fs-sm); color: var(--fg-2); min-width: 80px; }
  201. .m-bar__val { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--fg); font-weight: 600; min-width: 44px; text-align: right; }
  202. .m-bar__prog { flex: 1; }
  203. /* Table */
  204. .tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
  205. .tbl th { text-align: left; font-weight: 600; color: var(--muted); padding: 10px var(--gap-sm); border-bottom: 1px solid var(--border); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.5px; }
  206. .tbl td { padding: 10px var(--gap-sm); border-bottom: 1px solid var(--border-light); color: var(--fg-2); }
  207. .tbl tr:nth-child(even) td { background: var(--accent-micro); }
  208. .tbl tr:hover td { background: var(--accent-hover-bg); }
  209. .tbl__link { color: var(--dark); font-weight: 500; cursor: pointer; }
  210. .tbl__link:hover { color: var(--accent-hover); }
  211. /* Grid helpers */
  212. .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-md); }
  213. .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap-md); }
  214. .grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap-md); }
  215. .flex-between { display: flex; align-items: center; justify-content: space-between; }
  216. .flex-wrap { display: flex; flex-wrap: wrap; gap: var(--gap-sm); }
  217. .gap-md { gap: var(--gap-md); }
  218. .gap-sm { gap: var(--gap-sm); }
  219. .mt-xs { margin-top: var(--gap-xs); }
  220. .mt-sm { margin-top: var(--gap-sm); }
  221. .mt-md { margin-top: var(--gap-md); }
  222. .mt-lg { margin-top: var(--gap-lg); }
  223. .mb-sm { margin-bottom: var(--gap-sm); }
  224. .mb-md { margin-bottom: var(--gap-md); }
  225. .mb-lg { margin-bottom: var(--gap-lg); }
  226. .text-muted { color: var(--muted); }
  227. .text-accent { color: var(--accent); }
  228. .text-danger { color: var(--red-text); }
  229. .text-sm { font-size: var(--fs-sm); }
  230. .text-xs { font-size: var(--fs-xs); }
  231. .mono { font-family: var(--font-mono); }
  232. /* Form */
  233. .fld { margin-bottom: var(--gap-md); }
  234. .fld label { display: block; font-size: var(--fs-sm); font-weight: 500; color: var(--fg-2); margin-bottom: 4px; }
  235. .fld input, .fld select, .fld textarea {
  236. width: 100%; padding: 10px 14px; font-size: var(--fs-body); font-family: var(--font-body);
  237. border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface);
  238. color: var(--fg); outline: none; transition: border-color .15s;
  239. }
  240. .fld input:focus, .fld select:focus, .fld textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
  241. /* Timeline */
  242. .tl { position: relative; padding-left: 28px; }
  243. .tl::before { content:''; position: absolute; left: 8px; top: 4px; bottom: 4px; width: 2px; background: var(--border); }
  244. .tl__item { position: relative; padding-bottom: var(--gap-lg); }
  245. .tl__item:last-child { padding-bottom: 0; }
  246. .tl__dot { position: absolute; left: -23px; top: 5px; width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--accent); background: var(--surface); }
  247. .tl__dot--done { background: var(--accent); }
  248. .tl__dot--warn { border-color: var(--orange); background: var(--orange); }
  249. .tl__dot--active { background: var(--surface); box-shadow: 0 0 0 3px var(--accent-glow); }
  250. .tl__title { font-weight: 600; font-size: var(--fs-body); color: var(--fg); }
  251. .tl__desc { font-size: var(--fs-sm); color: var(--muted); margin-top: 2px; }
  252. /* Tree */
  253. .tree { list-style: none; padding: 0; }
  254. .tree li { position: relative; padding: 6px 0 6px 24px; font-size: var(--fs-sm); }
  255. .tree li::before { content:''; position: absolute; left: 8px; top: 0; bottom: 50%; width: 1px; background: var(--border); }
  256. .tree li::after { content:''; position: absolute; left: 8px; top: 50%; width: 12px; height: 1px; background: var(--border); }
  257. .tree li:last-child::before { height: 50%; }
  258. .tree__node { font-weight: 600; color: var(--fg); }
  259. .tree__leaf { color: var(--fg-2); }
  260. /* Notification */
  261. .notif { display: flex; gap: var(--gap-sm); padding: var(--gap-sm) 0; border-bottom: 1px solid var(--border-light); cursor: pointer; transition: background .12s; }
  262. .notif:hover { background: var(--accent-micro); }
  263. .notif--unread { background: var(--accent-soft); }
  264. .notif__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex-shrink: 0; margin-top: 6px; }
  265. .notif__body { flex: 1; }
  266. .notif__title { font-size: var(--fs-sm); font-weight: 600; color: var(--fg); }
  267. .notif__desc { font-size: var(--fs-xs); color: var(--muted); margin-top: 2px; }
  268. .notif__time { font-size: var(--fs-xs); color: var(--meta); white-space: nowrap; }
  269. /* Chat / feedback */
  270. .chat { display: flex; flex-direction: column; gap: var(--gap-sm); }
  271. .chat__msg { max-width: 75%; padding: 12px 16px; border-radius: var(--radius-md); font-size: var(--fs-sm); line-height: 1.5; }
  272. .chat__msg--in { align-self: flex-start; background: var(--surface); border: 1px solid var(--border); }
  273. .chat__msg--out { align-self: flex-end; background: var(--accent-soft); border: 1px solid var(--accent-glow); }
  274. .chat__msg--ai { align-self: flex-start; background: var(--indigo-soft); border: 1px solid var(--indigo-border); }
  275. .chat__meta { font-size: var(--fs-xs); color: var(--muted); margin-top: 4px; }
  276. /* Alignment tree */
  277. .align-tree { display: flex; flex-direction: column; align-items: center; gap: var(--gap-md); }
  278. .align-node {
  279. background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  280. padding: 10px 18px; font-size: var(--fs-sm); text-align: center; min-width: 160px;
  281. }
  282. .align-node--root { border-color: var(--dark); background: var(--indigo-soft); font-weight: 700; color: var(--dark); }
  283. .align-node--warn { border-color: var(--orange); background: var(--orange-bg); }
  284. .align-connector { width: 2px; height: 20px; background: var(--border); }
  285. .align-row { display: flex; gap: var(--gap-lg); justify-content: center; }
  286. .align-col { display: flex; flex-direction: column; align-items: center; gap: 4px; }
  287. /* Gantt */
  288. .gantt { display: flex; flex-direction: column; gap: 1px; background: var(--border-light); border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
  289. .gantt__row { display: flex; align-items: center; background: var(--surface); padding: 0; }
  290. .gantt__label { width: 160px; padding: 10px 14px; font-size: var(--fs-sm); font-weight: 500; color: var(--fg); flex-shrink: 0; }
  291. .gantt__track { flex: 1; height: 40px; position: relative; }
  292. .gantt__bar { position: absolute; top: 8px; height: 24px; border-radius: var(--radius-xs); display: flex; align-items: center; padding: 0 8px; font-size: 11px; font-weight: 600; color: #fff; }
  293. .gantt__bar--accent { background: var(--accent); color: var(--dark); }
  294. .gantt__bar--indigo { background: var(--dark); }
  295. .gantt__bar--orange { background: var(--orange); }
  296. .gantt__bar--red { background: var(--red); }
  297. .gantt__bar--green { background: var(--success); }
  298. .gantt__marker { position: absolute; top: 4px; width: 2px; height: 32px; background: var(--red); }
  299. /* Org chart */
  300. .org-node {
  301. display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  302. border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface);
  303. cursor: pointer; transition: border-color .15s;
  304. }
  305. .org-node:hover { border-color: var(--accent); }
  306. .org-node__avatar { width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; color: #fff; flex-shrink: 0; }
  307. .org-node__name { font-weight: 600; font-size: var(--fs-sm); }
  308. .org-node__role { font-size: var(--fs-xs); color: var(--muted); }
  309. /* Appeal status flow */
  310. .flow { display: flex; align-items: center; gap: 0; }
  311. .flow__step { display: flex; align-items: center; gap: 6px; font-size: var(--fs-sm); color: var(--muted); padding: 6px 12px; border-radius: var(--radius-pill); background: var(--surface-alt); }
  312. .flow__step--done { color: var(--green-text); background: var(--green-bg); }
  313. .flow__step--active { color: var(--accent-hover); background: var(--accent-soft); font-weight: 600; }
  314. .flow__step--reject { color: var(--red-text); background: var(--red-bg); }
  315. .flow__arrow { color: var(--meta); margin: 0 2px; font-size: 10px; }
  316. /* Slider */
  317. input[type=range] { -webkit-appearance: none; width: 100%; height: 6px; border-radius: 3px; background: var(--border-light); outline: none; }
  318. input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; border-radius: 50%; background: var(--accent); cursor: pointer; border: none; }
  319. /* Login page special */
  320. .login-page { display: flex; height: 100vh; }
  321. .login-brand {
  322. flex: 1; background: var(--dark); display: flex; flex-direction: column;
  323. align-items: center; justify-content: center; padding: var(--gap-xl); color: var(--on-dark);
  324. }
  325. .login-brand h1 { font-family: var(--font-display); font-size: var(--fs-hero); font-weight: 700; letter-spacing: -0.5px; }
  326. .login-brand h1 span { color: var(--accent); }
  327. .login-brand p { font-size: var(--fs-lead); color: rgba(255,255,255,0.7); margin-top: var(--gap-sm); max-width: 360px; text-align: center; }
  328. .login-brand__stats { display: flex; gap: var(--gap-xl); margin-top: var(--gap-xl); }
  329. .login-brand__stat { text-align: center; }
  330. .login-brand__stat b { display: block; font-family: var(--font-display); font-size: 32px; color: var(--accent); }
  331. .login-brand__stat span { font-size: var(--fs-sm); color: rgba(255,255,255,0.6); }
  332. .login-form {
  333. width: 440px; display: flex; flex-direction: column; justify-content: center; padding: var(--gap-xl);
  334. }
  335. .login-form h2 { font-size: var(--fs-h2); font-weight: 600; margin-bottom: var(--gap-xs); }
  336. .login-form .sub { color: var(--muted); font-size: var(--fs-sm); margin-bottom: var(--gap-lg); }
  337. /* Scrollbar */
  338. ::-webkit-scrollbar { width: 6px; }
  339. ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
  340. /* Responsive */
  341. @media (max-width: 860px) {
  342. .sidebar { display: none; }
  343. .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  344. .login-form { width: 100%; }
  345. .login-brand { display: none; }
  346. }
  347. @media (max-width: 1100px) {
  348. .grid-4 { grid-template-columns: 1fr 1fr; }
  349. }
  350. </style>
  351. </head>
  352. <body>
  353. <div class="app" id="app">
  354. <!-- ═══ Sidebar ═══ -->
  355. <nav class="sidebar" id="sidebar">
  356. <div class="sidebar-brand">医梦<span>AI</span> · OKR</div>
  357. <div class="nav-module" id="mod-workspace">
  358. <div class="nav-module__header" onclick="toggleMod('mod-workspace')">🏠 工作台 <span class="nav-module__arrow">▾</span></div>
  359. <div class="nav-item nav-item--active" data-page="login" onclick="navTo('login',this)"><span class="nav-item__icon">🔑</span> 登录</div>
  360. <div class="nav-item" data-page="workspace" onclick="navTo('workspace',this)"><span class="nav-item__icon">🏠</span> 工作台</div>
  361. </div>
  362. <div class="nav-module" id="mod-okr">
  363. <div class="nav-module__header" onclick="toggleMod('mod-okr')">📋 OKR <span class="nav-module__arrow">▾</span></div>
  364. <div class="nav-item" data-page="my-okr" onclick="navTo('my-okr',this)"><span class="nav-item__icon">🎯</span> 我的 OKR</div>
  365. <div class="nav-item" data-page="team-okr" onclick="navTo('team-okr',this)"><span class="nav-item__icon">👥</span> 团队 OKR</div>
  366. <div class="nav-item" data-page="okr-align" onclick="navTo('okr-align',this)"><span class="nav-item__icon">🔗</span> OKR 对齐</div>
  367. <div class="nav-item" data-page="okr-exec" onclick="navTo('okr-exec',this)"><span class="nav-item__icon">📈</span> 执行进度</div>
  368. </div>
  369. <div class="nav-module" id="mod-score">
  370. <div class="nav-module__header" onclick="toggleMod('mod-score')">📊 绩效 <span class="nav-module__arrow">▾</span></div>
  371. <div class="nav-item" data-page="my-result" onclick="navTo('my-result',this)"><span class="nav-item__icon">⭐</span> 我的绩效</div>
  372. <div class="nav-item" data-page="score-history" onclick="navTo('score-history',this)"><span class="nav-item__icon">📅</span> 历史绩效</div>
  373. <div class="nav-item" data-page="scoring-list" onclick="navTo('scoring-list',this)"><span class="nav-item__icon">✏️</span> 绩效打分</div>
  374. <div class="nav-item" data-page="scoring-detail" onclick="navTo('scoring-detail',this)"><span class="nav-item__icon">📝</span> 绩效考评</div>
  375. <div class="nav-item" data-page="appeal" onclick="navTo('appeal',this)"><span class="nav-item__icon">⚖️</span> 绩效申诉</div>
  376. <div class="nav-item" data-page="feedback" onclick="navTo('feedback',this)"><span class="nav-item__icon">💬</span> 绩效沟通</div>
  377. </div>
  378. <div class="nav-module" id="mod-admin">
  379. <div class="nav-module__header" onclick="toggleMod('mod-admin')">⚙️ 管理 <span class="nav-module__arrow">▾</span></div>
  380. <div class="nav-item" data-page="periods" onclick="navTo('periods',this)"><span class="nav-item__icon">🔄</span> 考核周期</div>
  381. <div class="nav-item" data-page="templates" onclick="navTo('templates',this)"><span class="nav-item__icon">📐</span> 绩效模板</div>
  382. <div class="nav-item" data-page="dimensions" onclick="navTo('dimensions',this)"><span class="nav-item__icon">📏</span> 考核维度</div>
  383. <div class="nav-item" data-page="org" onclick="navTo('org',this)"><span class="nav-item__icon">🏛️</span> 组织架构</div>
  384. </div>
  385. <div class="nav-module" id="mod-sys">
  386. <div class="nav-module__header" onclick="toggleMod('mod-sys')">🔔 系统 <span class="nav-module__arrow">▾</span></div>
  387. <div class="nav-item" data-page="notifications" onclick="navTo('notifications',this)"><span class="nav-item__icon">🔔</span> 消息通知<span class="nav-item__dot"></span></div>
  388. <div class="nav-item" data-page="logs" onclick="navTo('logs',this)"><span class="nav-item__icon">📋</span> 操作日志</div>
  389. </div>
  390. </nav>
  391. <!-- ═══ Main ═══ -->
  392. <div class="main">
  393. <div class="topbar">
  394. <div class="topbar__left"><span class="topbar__title" id="topbarTitle">登录</span></div>
  395. <div class="topbar__actions">
  396. <span style="font-size:var(--fs-sm);color:var(--muted);">2025 Q4 · 年度考核</span>
  397. <div class="topbar__avatar">李</div>
  398. </div>
  399. </div>
  400. <!-- ═══════════════════════════════════════════════════════════════
  401. PAGE PANELS — 18 pages
  402. ═══════════════════════════════════════════════════════════════ -->
  403. <!-- ── LOGIN ──────────────────────────────────────────────── -->
  404. <div class="login-page page-panel page-panel--active" id="pg-login" style="padding:0;">
  405. <div class="login-brand">
  406. <h1>医梦<span>AI</span></h1>
  407. <p>AI 驱动的智慧医疗绩效管理平台 — 让每一份付出都被看见</p>
  408. <div class="login-brand__stats">
  409. <div class="login-brand__stat"><b>1,280</b><span>活跃用户</span></div>
  410. <div class="login-brand__stat"><b>98.6%</b><span>评分完成率</span></div>
  411. <div class="login-brand__stat"><b>42</b><span>医院科室</span></div>
  412. </div>
  413. </div>
  414. <div class="login-form">
  415. <h2>欢迎回来</h2>
  416. <p class="sub">登录你的 OKR 绩效账户</p>
  417. <div class="fld"><label>邮箱 / 工号</label><input type="text" placeholder="liming@emoon-med.com" value="liming@emoon-med.com"></div>
  418. <div class="fld"><label>密码</label><input type="password" placeholder="······" value="123456"></div>
  419. <button class="btn btn-primary" style="width:100%;justify-content:center;margin-top:var(--gap-sm);" onclick="navTo('workspace')">登录</button>
  420. <p style="text-align:center;margin-top:var(--gap-md);font-size:var(--fs-sm);color:var(--muted);">演示模式 — 点击登录查看完整原型</p>
  421. </div>
  422. </div>
  423. <!-- ── WORKSPACE ───────────────────────────────────────────── -->
  424. <div class="page-panel" id="pg-workspace">
  425. <div class="s-head"><div class="s-head__left"><h2>工作台</h2><p>下午好,李明医生 — 2025 Q4 考核周期还有 18 天结束</p></div><button class="btn btn-outline btn-sm">📅 切换周期</button></div>
  426. <div class="grid-4 mb-md">
  427. <div class="stat-card"><div class="stat-card__top stat-card__top--accent"></div><div class="stat-card__num">8</div><div class="stat-card__label">我的 OKR 目标</div><div class="text-xs text-muted mt-xs">4 个进行中 · 3 个已完成</div></div>
  428. <div class="stat-card"><div class="stat-card__top stat-card__top--indigo"></div><div class="stat-card__num">76%</div><div class="stat-card__label">总体完成进度</div><div class="text-xs text-muted mt-xs">较上月 +5%</div></div>
  429. <div class="stat-card"><div class="stat-card__top stat-card__top--orange"></div><div class="stat-card__num">86</div><div class="stat-card__label">当前绩效评分</div><div class="text-xs text-muted mt-xs">评级 A · 待上级确认</div></div>
  430. <div class="stat-card"><div class="stat-card__top stat-card__top--red"></div><div class="stat-card__num">2</div><div class="stat-card__label">待处理预警</div><div class="text-xs text-danger mt-xs">1 项超时 · 1 项评分异常</div></div>
  431. </div>
  432. <div class="grid-2 mb-md">
  433. <div class="card card--lg" style="background:var(--dark);color:var(--on-dark);">
  434. <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px;"><span class="tag tag-accent">AI 洞察</span><span style="font-size:var(--fs-xs);color:rgba(255,255,255,0.5);">基于历史数据生成</span></div>
  435. <p style="font-size:var(--fs-body);opacity:0.9;line-height:1.6;">当前周期你的「患者满意度」KR 滞后同期 14%,建议本周增加门诊随访频次至每日 ≥ 5 例。<b style="color:var(--accent);">转化率 18%</b> 超出预期 3 个百分点,继续保持。</p>
  436. <div class="flex-between mt-md">
  437. <span class="tag tag-warn">⚠ 延迟 14%</span><button class="btn btn-sm" style="background:rgba(255,255,255,0.15);color:#fff;">查看详情 →</button>
  438. </div>
  439. </div>
  440. <div class="card" style="display:flex;flex-direction:column;">
  441. <div class="flex-between mb-sm"><strong style="font-size:var(--fs-body);">待办事项</strong><span class="tag tag-accent">3 项</span></div>
  442. <div style="font-size:var(--fs-sm);color:var(--fg-2);padding:8px 0;border-bottom:1px solid var(--border-light);">📌 完成 Q4 自评报告 <span class="tag tag-warn" style="float:right;">明天截止</span></div>
  443. <div style="font-size:var(--fs-sm);color:var(--fg-2);padding:8px 0;border-bottom:1px solid var(--border-light);">📌 审核张护士的 OKR 对齐申请 <span class="tag tag-muted" style="float:right;">3天后</span></div>
  444. <div style="font-size:var(--fs-sm);color:var(--fg-2);padding:8px 0;">📌 提交科室设备采购绩效指标 <span style="float:right;color:var(--red-text);font-size:var(--fs-xs);">⏰ 已超时 2 天</span></div>
  445. </div>
  446. </div>
  447. <div class="card mb-md">
  448. <div class="flex-between mb-sm"><strong style="font-size:var(--fs-body);">团队绩效概览</strong><span class="text-sm text-muted">神经内科 · 12 人</span></div>
  449. <table class="tbl"><thead><tr><th>成员</th><th>OKR 进度</th><th>评分</th><th>状态</th><th>预警</th></tr></thead><tbody>
  450. <tr><td><span class="tbl__link">李明</span></td><td><div class="m-bar"><div class="m-bar__prog"><div class="prog"><div class="prog__fill prog__fill--accent" style="width:76%"></div></div></div><span class="mono text-sm">76%</span></div></td><td class="mono">86</td><td><span class="tag tag-success">正常</span></td><td>—</td></tr>
  451. <tr><td><span class="tbl__link">张伟</span></td><td><div class="m-bar"><div class="m-bar__prog"><div class="prog"><div class="prog__fill prog__fill--indigo" style="width:92%"></div></div></div><span class="mono text-sm">92%</span></div></td><td class="mono">93</td><td><span class="tag tag-success">正常</span></td><td>—</td></tr>
  452. <tr><td><span class="tbl__link">王芳</span></td><td><div class="m-bar"><div class="m-bar__prog"><div class="prog"><div class="prog__fill prog__fill--orange" style="width:45%"></div></div></div><span class="mono text-sm">45%</span></div></td><td class="mono">62</td><td><span class="tag tag-warn">延迟</span></td><td><span class="tag tag-warn">超时</span></td></tr>
  453. <tr><td><span class="tbl__link">赵丽</span></td><td><div class="m-bar"><div class="m-bar__prog"><div class="prog"><div class="prog__fill prog__fill--red" style="width:28%"></div></div></div><span class="mono text-sm">28%</span></div></td><td class="mono">—</td><td><span class="tag tag-danger">严重</span></td><td><span class="tag tag-danger">落后</span></td></tr>
  454. </tbody></table>
  455. </div>
  456. </div>
  457. <!-- ── MY OKR ──────────────────────────────────────────────── -->
  458. <div class="page-panel" id="pg-my-okr">
  459. <div class="s-head"><div class="s-head__left"><h2>我的 OKR</h2><p>2025 Q4 · 神经内科主治医师</p></div><div class="flex-wrap"><button class="btn btn-outline btn-sm">📥 导入</button><button class="btn btn-primary btn-sm">+ 新建 KR</button></div></div>
  460. <div class="card mb-md" style="border-left:4px solid var(--dark);">
  461. <div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;"><span class="tag tag-indigo">O1</span><span style="font-weight:700;font-size:var(--fs-h3);color:var(--fg);">提升门诊诊疗效率与患者满意度</span><span class="tag tag-accent">权重 40%</span></div>
  462. <p style="font-size:var(--fs-sm);color:var(--muted);margin-bottom:var(--gap-md);">通过 AI 辅助问诊和流程优化,将平均就诊等待时间从 18 分钟降至 10 分钟以内,患者满意度评分达到 4.5/5。</p>
  463. <div style="display:flex;flex-direction:column;gap:10px;">
  464. <div class="card card--flat" style="border-left:4px solid var(--accent);">
  465. <div class="flex-between"><div><span class="tag tag-accent">KR1.1</span> <strong>AI 预问诊覆盖率 ≥ 60%</strong><span class="mono text-sm" style="margin-left:8px;">当前 52%</span></div><span class="tag tag-success">进行中</span></div>
  466. <div class="prog mt-sm"><div class="prog__fill prog__fill--accent" style="width:52%"></div></div>
  467. </div>
  468. <div class="card card--flat" style="border-left:4px solid var(--dark);">
  469. <div class="flex-between"><div><span class="tag tag-indigo">KR1.2</span> <strong>平均候诊时间 ≤ 10 分钟</strong><span class="mono text-sm" style="margin-left:8px;">当前 14 分钟</span></div><span class="tag tag-success">进行中</span></div>
  470. <div class="prog mt-sm"><div class="prog__fill prog__fill--indigo" style="width:60%"></div></div>
  471. </div>
  472. <div class="card card--flat" style="border-left:4px solid var(--dark);">
  473. <div class="flex-between"><div><span class="tag tag-indigo">KR1.3</span> <strong>患者满意度 ≥ 4.5/5</strong><span class="mono text-sm" style="margin-left:8px;">当前 4.2</span></div><span class="tag tag-success">进行中</span></div>
  474. <div class="prog mt-sm"><div class="prog__fill prog__fill--indigo" style="width:70%"></div></div>
  475. </div>
  476. <div class="card card--flat" style="border-left:4px solid var(--red);">
  477. <div class="flex-between"><div><span class="tag tag-danger">KR1.4</span> <strong>门诊电子病历完整率 ≥ 95%</strong><span class="mono text-sm text-danger" style="margin-left:8px;">当前 33%</span></div><span class="tag tag-warn">延迟</span></div>
  478. <div class="prog mt-sm"><div class="prog__fill prog__fill--red" style="width:33%"></div></div>
  479. </div>
  480. </div>
  481. </div>
  482. <div class="card mb-md" style="border-left:4px solid var(--accent);">
  483. <div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;"><span class="tag tag-indigo">O2</span><span style="font-weight:700;font-size:var(--fs-h3);color:var(--fg);">推动科室 AI 质控体系建设</span><span class="tag tag-accent">权重 30%</span></div>
  484. <p style="font-size:var(--fs-sm);color:var(--muted);margin-bottom:var(--gap-md);">建立基于 AI 的病历质控闭环,实现病历缺陷自动检测与实时提醒。</p>
  485. <div style="display:flex;flex-direction:column;gap:10px;">
  486. <div class="card card--flat" style="border-left:4px solid var(--accent);"><div class="flex-between"><div><span class="tag tag-accent">KR2.1</span> <strong>病历 AI 质控覆盖 100% 出院病历</strong></div><span class="tag tag-success">已完成</span></div><div class="prog mt-sm"><div class="prog__fill prog__fill--green" style="width:100%"></div></div></div>
  487. <div class="card card--flat" style="border-left:4px solid var(--accent);"><div class="flex-between"><div><span class="tag tag-accent">KR2.2</span> <strong>病历缺陷率降至 5% 以下</strong></div><span class="tag tag-success">已完成</span></div><div class="prog mt-sm"><div class="prog__fill prog__fill--green" style="width:100%"></div></div></div>
  488. </div>
  489. </div>
  490. <div class="card">
  491. <strong style="font-size:var(--fs-body);">承接上级目标</strong>
  492. <table class="tbl mt-sm"><thead><tr><th>上级目标</th><th>负责人</th><th>对齐关系</th><th>进度</th></tr></thead><tbody>
  493. <tr><td>神经内科综合服务能力提升 20%</td><td>王主任</td><td>→ O1 提升门诊诊疗效率</td><td><div class="prog" style="width:120px;"><div class="prog__fill prog__fill--accent" style="width:65%"></div></div></td></tr>
  494. <tr><td>全院 AI 质控平台上线</td><td>陈院长</td><td>→ O2 科室 AI 质控体系</td><td><div class="prog" style="width:120px;"><div class="prog__fill prog__fill--green" style="width:100%"></div></div></td></tr>
  495. </tbody></table>
  496. </div>
  497. </div>
  498. <!-- ── TEAM OKR ────────────────────────────────────────────── -->
  499. <div class="page-panel" id="pg-team-okr">
  500. <div class="s-head"><div class="s-head__left"><h2>团队 OKR</h2><p>神经内科 · 12 名成员 · 2025 Q4</p></div><div class="flex-wrap"><button class="btn btn-outline btn-sm">📥 导出</button><button class="btn btn-primary btn-sm">+ 新建团队目标</button></div></div>
  501. <div class="card mb-md" style="border-left:4px solid var(--dark);">
  502. <div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;"><span class="tag tag-indigo">部门 O</span><span style="font-weight:700;font-size:var(--fs-h3);">神经内科综合服务能力提升 20%</span><span class="tag tag-accent">权重 50%</span></div>
  503. <div style="display:flex;flex-direction:column;gap:10px;margin-bottom:var(--gap-md);">
  504. <div class="card card--flat" style="border-left:4px solid var(--accent);"><div class="flex-between"><span><span class="tag tag-accent">KR-A</span> 门诊量同比 +15%</span><span class="mono text-sm">82%</span></div><div class="prog mt-xs"><div class="prog__fill prog__fill--accent" style="width:82%"></div></div></div>
  505. <div class="card card--flat" style="border-left:4px solid var(--accent);"><div class="flex-between"><span><span class="tag tag-accent">KR-B</span> 患者满意度 ≥ 4.3</span><span class="mono text-sm">70%</span></div><div class="prog mt-xs"><div class="prog__fill prog__fill--indigo" style="width:70%"></div></div></div>
  506. </div>
  507. </div>
  508. <div class="flex-between mb-md"><strong style="font-size:var(--fs-body);">成员 OKR 概览</strong><span class="text-sm text-muted">按进度排序</span></div>
  509. <div class="grid-2">
  510. <div class="card"><div class="flex-between mb-sm"><span class="tbl__link">张伟 · 副主任医师</span><span class="tag tag-success">92%</span></div><div class="prog mb-xs"><div class="prog__fill prog__fill--green" style="width:92%"></div></div><span class="text-xs text-muted">4 KR · 3 完成 · 1 进行中</span></div>
  511. <div class="card"><div class="flex-between mb-sm"><span class="tbl__link">刘洋 · 主治医师</span><span class="tag tag-accent">84%</span></div><div class="prog mb-xs"><div class="prog__fill prog__fill--accent" style="width:84%"></div></div><span class="text-xs text-muted">5 KR · 3 完成 · 2 进行中</span></div>
  512. <div class="card"><div class="flex-between mb-sm"><span class="tbl__link">李明 · 主治医师</span><span class="tag tag-accent">76%</span></div><div class="prog mb-xs"><div class="prog__fill prog__fill--accent" style="width:76%"></div></div><span class="text-xs text-muted">6 KR · 2 完成 · 3 进行中 · 1 延迟</span></div>
  513. <div class="card"><div class="flex-between mb-sm"><span class="tbl__link">王芳 · 住院医师</span><span class="tag tag-warn">45%</span></div><div class="prog mb-xs"><div class="prog__fill prog__fill--orange" style="width:45%"></div></div><span class="text-xs text-danger">3 KR · 0 完成 · 2 进行中 · 1 超时</span></div>
  514. <div class="card"><div class="flex-between mb-sm"><span class="tbl__link">赵丽 · 住院医师</span><span class="tag tag-danger">28%</span></div><div class="prog mb-xs"><div class="prog__fill prog__fill--red" style="width:28%"></div></div><span class="text-xs text-danger">2 KR · 0 完成 · 1 进行中 · 1 严重落后</span></div>
  515. <div class="card"><div class="flex-between mb-sm"><span class="tbl__link">陈静 · 护士长</span><span class="tag tag-success">95%</span></div><div class="prog mb-xs"><div class="prog__fill prog__fill--green" style="width:95%"></div></div><span class="text-xs text-muted">3 KR · 3 完成</span></div>
  516. </div>
  517. </div>
  518. <!-- ── OKR ALIGNMENT ───────────────────────────────────────── -->
  519. <div class="page-panel" id="pg-okr-align">
  520. <div class="s-head"><div class="s-head__left"><h2>OKR 对齐</h2><p>可视化目标层级关系 · 检测未对齐节点</p></div><button class="btn btn-outline btn-sm">🔍 检测未对齐</button></div>
  521. <div class="card mb-md" style="overflow-x:auto;padding:var(--gap-lg);">
  522. <div class="align-tree">
  523. <div class="align-node align-node--root">🏥 全院 AI 质控平台上线<br><span class="text-xs" style="color:var(--muted);">陈院长 · 权重 40%</span></div>
  524. <div class="align-connector"></div>
  525. <div class="align-row">
  526. <div class="align-col"><div class="align-connector"></div><div class="align-node">神经内科综合服务能力<br><span class="text-xs text-muted">王主任</span></div><div class="align-connector"></div><div class="align-node" style="border-color:var(--accent);">提升门诊诊疗效率<br><span class="text-xs text-muted">李明</span></div></div>
  527. <div class="align-col"><div class="align-connector"></div><div class="align-node">心内科质控达标<br><span class="text-xs text-muted">赵主任</span></div></div>
  528. <div class="align-col"><div class="align-connector"></div><div class="align-node align-node--warn">⚠ 骨科科室 OKR<br><span class="text-xs" style="color:var(--orange-text);">未对齐全院目标</span></div></div>
  529. </div>
  530. </div>
  531. </div>
  532. <div class="card">
  533. <div class="flex-between mb-sm"><strong style="font-size:var(--fs-body);">对齐异常</strong><span class="tag tag-danger">2 项</span></div>
  534. <table class="tbl"><thead><tr><th>部门/个人</th><th>问题</th><th>影响</th><th>建议</th><th>操作</th></tr></thead><tbody>
  535. <tr><td>骨科</td><td><span class="tag tag-danger">未对齐</span></td><td>科室 OKR 与全院目标无连接</td><td class="text-sm">建议关联「全院质控平台」目标</td><td><button class="btn btn-outline btn-sm">发起对齐</button></td></tr>
  536. <tr><td>赵丽</td><td><span class="tag tag-warn">未对齐</span></td><td>个人 OKR 未承接上级目标</td><td class="text-sm">建议对齐王主任「综合服务能力」KR</td><td><button class="btn btn-outline btn-sm">发起对齐</button></td></tr>
  537. </tbody></table>
  538. </div>
  539. </div>
  540. <!-- ── OKR EXECUTION ───────────────────────────────────────── -->
  541. <div class="page-panel" id="pg-okr-exec">
  542. <div class="s-head"><div class="s-head__left"><h2>执行进度</h2><p>Q4 关键结果时间线 · 10 月 — 12 月</p></div><button class="btn btn-outline btn-sm">📥 导出报告</button></div>
  543. <div class="card mb-md">
  544. <div class="gantt">
  545. <div class="gantt__row"><div class="gantt__label">AI 预问诊覆盖</div><div class="gantt__track"><div class="gantt__bar gantt__bar--accent" style="left:0;width:58%;">52%</div></div></div>
  546. <div class="gantt__row"><div class="gantt__label">候诊时间优化</div><div class="gantt__track"><div class="gantt__bar gantt__bar--accent" style="left:0;width:66%;">60%</div></div></div>
  547. <div class="gantt__row"><div class="gantt__label">患者满意度</div><div class="gantt__track"><div class="gantt__bar gantt__bar--indigo" style="left:0;width:72%;">70%</div></div></div>
  548. <div class="gantt__row"><div class="gantt__label">病历完整率</div><div class="gantt__track"><div class="gantt__bar gantt__bar--red" style="left:0;width:33%;">33%</div><div class="gantt__marker" style="left:66%;"></div></div></div>
  549. </div>
  550. <div class="text-xs text-muted mt-sm">红色标记 = 预期进度线(当前应达 66%)· 滑块位置 = 实际进度</div>
  551. </div>
  552. <div class="grid-2 mb-md">
  553. <div class="card"><strong style="font-size:var(--fs-body);">里程碑</strong>
  554. <div class="tl mt-sm">
  555. <div class="tl__item"><div class="tl__dot tl__dot--done"></div><div class="tl__title">Q4 目标制定</div><div class="tl__desc">2025-10-01 · 已完成</div></div>
  556. <div class="tl__item"><div class="tl__dot tl__dot--done"></div><div class="tl__title">中期回顾</div><div class="tl__desc">2025-11-15 · 已完成</div></div>
  557. <div class="tl__item"><div class="tl__dot tl__dot--active"></div><div class="tl__title">自评提交截止</div><div class="tl__desc">2025-12-20 · 进行中</div></div>
  558. <div class="tl__item"><div class="tl__dot"></div><div class="tl__title">上级评审</div><div class="tl__desc">2025-12-31 · 待开始</div></div>
  559. </div>
  560. </div>
  561. <div class="card"><strong style="font-size:var(--fs-body);">风险预警</strong>
  562. <div style="padding:10px 0;border-bottom:1px solid var(--border-light);"><span class="tag tag-danger mb-sm">🔴 严重</span><p class="text-sm mt-xs">赵丽 — 2 项 KR 均严重落后,无提交记录</p></div>
  563. <div style="padding:10px 0;border-bottom:1px solid var(--border-light);"><span class="tag tag-warn mb-sm">🟠 超时</span><p class="text-sm mt-xs">王芳 — 「病历规范率」KR 超时未更新</p></div>
  564. <div style="padding:10px 0;"><span class="tag tag-muted mb-sm">🟡 待处理</span><p class="text-sm mt-xs">3 名成员尚未提交中期自评</p></div>
  565. </div>
  566. </div>
  567. </div>
  568. <!-- ── MY RESULT ───────────────────────────────────────────── -->
  569. <div class="page-panel" id="pg-my-result">
  570. <div class="s-head"><div class="s-head__left"><h2>我的绩效</h2><p>2025 Q4 · 李明 · 神经内科主治医师</p></div><button class="btn btn-outline btn-sm">📄 查看详情</button></div>
  571. <div class="grid-3 mb-md">
  572. <div class="stat-card" style="text-align:center;"><div class="stat-card__num text-accent" style="font-size:64px;">86</div><div class="stat-card__label">综合得分</div><span class="tag tag-success mt-xs">A 级</span></div>
  573. <div class="card" style="display:flex;flex-direction:column;justify-content:center;">
  574. <div class="m-bar mb-sm"><span class="m-bar__label">OKR 达成</span><span class="m-bar__val mono">85</span><div class="m-bar__prog"><div class="prog"><div class="prog__fill prog__fill--accent" style="width:85%"></div></div></div></div>
  575. <div class="m-bar mb-sm"><span class="m-bar__label">KPI 指标</span><span class="m-bar__val mono">82</span><div class="m-bar__prog"><div class="prog"><div class="prog__fill prog__fill--indigo" style="width:82%"></div></div></div></div>
  576. <div class="m-bar mb-sm"><span class="m-bar__label">能力评估</span><span class="m-bar__val mono">90</span><div class="m-bar__prog"><div class="prog"><div class="prog__fill prog__fill--green" style="width:90%"></div></div></div></div>
  577. <div class="m-bar"><span class="m-bar__label">价值观</span><span class="m-bar__val mono">88</span><div class="m-bar__prog"><div class="prog"><div class="prog__fill prog__fill--accent" style="width:88%"></div></div></div></div>
  578. </div>
  579. <div class="card" style="display:flex;flex-direction:column;justify-content:center;">
  580. <div class="flex-between mb-sm"><span class="text-sm">自评分</span><span class="mono" style="font-size:24px;font-weight:700;color:var(--dark);">88</span></div>
  581. <div class="flex-between mb-sm"><span class="text-sm">上级终审</span><span class="mono" style="font-size:24px;font-weight:700;color:var(--accent);">86</span></div>
  582. <div class="flex-between mb-sm"><span class="text-sm">差距</span><span class="mono" style="font-size:24px;font-weight:700;color:var(--red-text);">-2</span></div>
  583. <div class="text-xs text-muted mt-sm">上级评语:整体表现优秀,AI 质控项目成果显著。建议下季度将门诊随访纳入 OKR。</div>
  584. </div>
  585. </div>
  586. <div class="card">
  587. <strong style="font-size:var(--fs-body);">扣分明细</strong>
  588. <table class="tbl mt-sm"><thead><tr><th>KR</th><th>目标值</th><th>实际值</th><th>得分率</th><th>扣分</th><th>说明</th></tr></thead><tbody>
  589. <tr><td>KR1.4 病历完整率</td><td class="mono">≥ 95%</td><td class="mono text-danger">33%</td><td><div class="prog" style="width:80px;"><div class="prog__fill prog__fill--red" style="width:34%"></div></div></td><td class="mono text-danger">-2</td><td class="text-sm">未达预期目标</td></tr>
  590. <tr><td>KR1.2 候诊时间</td><td class="mono">≤ 10min</td><td class="mono">14min</td><td><div class="prog" style="width:80px;"><div class="prog__fill prog__fill--orange" style="width:60%"></div></div></td><td class="mono" style="color:var(--orange-text);">-1</td><td class="text-sm">部分达成</td></tr>
  591. </tbody></table>
  592. </div>
  593. </div>
  594. <!-- ── SCORE HISTORY ───────────────────────────────────────── -->
  595. <div class="page-panel" id="pg-score-history">
  596. <div class="s-head"><div class="s-head__left"><h2>历史绩效</h2><p>李明 · 近 4 个季度趋势</p></div><button class="btn btn-outline btn-sm">📥 导出</button></div>
  597. <div class="card mb-md" style="padding:var(--gap-lg);">
  598. <div style="display:flex;align-items:flex-end;gap:40px;height:200px;padding:0 20px;">
  599. <div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;">
  600. <span class="mono" style="font-weight:700;color:var(--fg);">79</span>
  601. <div style="width:48px;background:rgba(43,31,153,0.25);border-radius:4px 4px 0 0;height:110px;"></div>
  602. <span class="text-xs text-muted">2025 Q1</span><span class="tag tag-muted">B+</span>
  603. </div>
  604. <div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;">
  605. <span class="mono" style="font-weight:700;color:var(--fg);">82</span>
  606. <div style="width:48px;background:rgba(43,31,153,0.45);border-radius:4px 4px 0 0;height:125px;"></div>
  607. <span class="text-xs text-muted">2025 Q2</span><span class="tag tag-muted">A-</span>
  608. </div>
  609. <div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;">
  610. <span class="mono" style="font-weight:700;color:var(--fg);">84</span>
  611. <div style="width:48px;background:rgba(43,31,153,0.65);border-radius:4px 4px 0 0;height:140px;"></div>
  612. <span class="text-xs text-muted">2025 Q3</span><span class="tag tag-muted">A-</span>
  613. </div>
  614. <div style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;">
  615. <span class="mono" style="font-weight:700;color:var(--accent);">86</span>
  616. <div style="width:48px;background:var(--accent);border-radius:4px 4px 0 0;height:155px;box-shadow:0 0 12px var(--accent-glow);"></div>
  617. <span class="text-xs text-muted">2025 Q4</span><span class="tag tag-success">A</span>
  618. </div>
  619. </div>
  620. </div>
  621. <div class="card">
  622. <strong style="font-size:var(--fs-body);">周期对比</strong>
  623. <table class="tbl mt-sm"><thead><tr><th>周期</th><th>OKR</th><th>KPI</th><th>能力</th><th>总分</th><th>评级</th><th>排名</th></tr></thead><tbody>
  624. <tr><td class="tbl__link">2025 Q4</td><td class="mono">85</td><td class="mono">82</td><td class="mono">90</td><td class="mono" style="color:var(--accent);font-weight:700;">86</td><td><span class="tag tag-success">A</span></td><td>3/12</td></tr>
  625. <tr><td class="tbl__link">2025 Q3</td><td class="mono">82</td><td class="mono">80</td><td class="mono">88</td><td class="mono">84</td><td><span class="tag tag-muted">A-</span></td><td>5/12</td></tr>
  626. <tr><td class="tbl__link">2025 Q2</td><td class="mono">80</td><td class="mono">78</td><td class="mono">86</td><td class="mono">82</td><td><span class="tag tag-muted">A-</span></td><td>6/12</td></tr>
  627. <tr><td class="tbl__link">2025 Q1</td><td class="mono">78</td><td class="mono">75</td><td class="mono">84</td><td class="mono">79</td><td><span class="tag tag-muted">B+</span></td><td>8/12</td></tr>
  628. </tbody></table>
  629. </div>
  630. </div>
  631. <!-- ── SCORING LIST ────────────────────────────────────────── -->
  632. <div class="page-panel" id="pg-scoring-list">
  633. <div class="s-head"><div class="s-head__left"><h2>绩效打分</h2><p>待评分人员 · 神经内科 · 2025 Q4</p></div><div class="flex-wrap"><button class="btn btn-outline btn-sm">📥 导出</button><button class="btn btn-primary btn-sm">批量评分</button></div></div>
  634. <div class="card">
  635. <div class="flex-between mb-sm"><div class="flex-wrap"><button class="btn btn-sm" style="background:var(--accent-soft);color:var(--accent-hover);border-radius:var(--radius-pill);">全部 (12)</button><button class="btn btn-ghost btn-sm">待评分 (4)</button><button class="btn btn-ghost btn-sm">已完成 (6)</button><button class="btn btn-ghost btn-sm">申诉中 (2)</button></div><span class="text-sm text-muted">已评 6/12</span></div>
  636. <table class="tbl"><thead><tr><th>成员</th><th>OKR 进度</th><th>自评分</th><th>状态</th><th>操作</th></tr></thead><tbody>
  637. <tr><td><span class="tbl__link">张伟</span></td><td><div class="prog" style="width:120px;"><div class="prog__fill prog__fill--green" style="width:92%"></div></div><span class="text-sm" style="margin-left:8px;">92%</span></td><td class="mono">91</td><td><span class="tag tag-warn">待评分</span></td><td><button class="btn btn-primary btn-sm">去评分</button></td></tr>
  638. <tr><td><span class="tbl__link">刘洋</span></td><td><div class="prog" style="width:120px;"><div class="prog__fill prog__fill--accent" style="width:84%"></div></div><span class="text-sm" style="margin-left:8px;">84%</span></td><td class="mono">85</td><td><span class="tag tag-warn">待评分</span></td><td><button class="btn btn-primary btn-sm">去评分</button></td></tr>
  639. <tr><td><span class="tbl__link">王芳</span></td><td><div class="prog" style="width:120px;"><div class="prog__fill prog__fill--orange" style="width:45%"></div></div><span class="text-sm" style="margin-left:8px;">45%</span></td><td class="mono">60</td><td><span class="tag tag-warn">待评分</span></td><td><button class="btn btn-primary btn-sm">去评分</button></td></tr>
  640. <tr><td><span class="tbl__link">赵丽</span></td><td><div class="prog" style="width:120px;"><div class="prog__fill prog__fill--red" style="width:28%"></div></div><span class="text-sm" style="margin-left:8px;">28%</span></td><td class="mono">55</td><td><span class="tag tag-warn">待评分</span></td><td><button class="btn btn-primary btn-sm">去评分</button></td></tr>
  641. <tr><td><span class="tbl__link">陈静</span></td><td><div class="prog" style="width:120px;"><div class="prog__fill prog__fill--green" style="width:95%"></div></div><span class="text-sm" style="margin-left:8px;">95%</span></td><td class="mono">94</td><td><span class="tag tag-success">已完成</span></td><td><button class="btn btn-outline btn-sm">查看</button></td></tr>
  642. <tr><td><span class="tbl__link">周涛</span></td><td><div class="prog" style="width:120px;"><div class="prog__fill prog__fill--green" style="width:88%"></div></div><span class="text-sm" style="margin-left:8px;">88%</span></td><td class="mono">87</td><td><span class="tag tag-danger">申诉中</span></td><td><button class="btn btn-outline btn-sm">处理</button></td></tr>
  643. </tbody></table>
  644. </div>
  645. </div>
  646. <!-- ── SCORING DETAIL ──────────────────────────────────────── -->
  647. <div class="page-panel" id="pg-scoring-detail">
  648. <div class="s-head"><div class="s-head__left"><h2>绩效考评</h2><p>被评人:张伟 · 神经内科副主任医师</p></div><div class="flex-wrap"><button class="btn btn-outline btn-sm">💾 暂存</button><button class="btn btn-primary btn-sm">提交评审</button></div></div>
  649. <div class="grid-2 mb-md">
  650. <div class="card"><strong style="font-size:var(--fs-body);">自评</strong><span class="text-xs text-muted" style="margin-left:8px;">张伟 提交于 12-15</span>
  651. <div style="margin-top:var(--gap-sm);display:flex;flex-direction:column;gap:12px;">
  652. <div><div class="flex-between text-sm"><span>OKR 达成</span><span class="mono">90</span></div><div class="prog mt-xs"><div class="prog__fill prog__fill--accent" style="width:90%"></div></div></div>
  653. <div><div class="flex-between text-sm"><span>KPI 指标</span><span class="mono">92</span></div><div class="prog mt-xs"><div class="prog__fill prog__fill--indigo" style="width:92%"></div></div></div>
  654. <div><div class="flex-between text-sm"><span>能力评估</span><span class="mono">88</span></div><div class="prog mt-xs"><div class="prog__fill prog__fill--green" style="width:88%"></div></div></div>
  655. <div style="background:var(--surface-alt);padding:10px;border-radius:var(--radius-sm);font-size:var(--fs-sm);">"本季度完成了神经介入手术质控标准制定,手术并发症率下降至 1.2%。"</div>
  656. </div>
  657. </div>
  658. <div class="card"><strong style="font-size:var(--fs-body);">上级评审</strong><span class="text-xs text-muted" style="margin-left:8px;">李明 · 当前评分人</span>
  659. <div style="margin-top:var(--gap-sm);display:flex;flex-direction:column;gap:12px;">
  660. <div><div class="flex-between text-sm"><span>OKR 达成</span><span class="mono" style="color:var(--accent);">88</span></div><input type="range" value="88" min="0" max="100" class="mt-xs"></div>
  661. <div><div class="flex-between text-sm"><span>KPI 指标</span><span class="mono" style="color:var(--accent);">90</span></div><input type="range" value="90" min="0" max="100" class="mt-xs"></div>
  662. <div><div class="flex-between text-sm"><span>能力评估</span><span class="mono" style="color:var(--accent);">92</span></div><input type="range" value="92" min="0" max="100" class="mt-xs"></div>
  663. <textarea placeholder="输入评语..." style="width:100%;padding:10px;border:1px solid var(--border);border-radius:var(--radius-sm);font-size:var(--fs-sm);resize:vertical;min-height:60px;">手术质控成果显著,建议将论文发表纳入下季度 OKR。</textarea>
  664. </div>
  665. </div>
  666. </div>
  667. <div class="card"><div class="flex-between"><strong style="font-size:var(--fs-body);">终审得分</strong><span class="mono" style="font-size:28px;font-weight:700;color:var(--accent);">90</span></div></div>
  668. </div>
  669. <!-- ── APPEAL ──────────────────────────────────────────────── -->
  670. <div class="page-panel" id="pg-appeal">
  671. <div class="s-head"><div class="s-head__left"><h2>绩效申诉</h2><p>申诉工单管理 · 2025 Q4</p></div><button class="btn btn-primary btn-sm">+ 发起申诉</button></div>
  672. <div class="card">
  673. <div class="flex-wrap mb-sm"><button class="btn btn-sm" style="background:var(--accent-soft);color:var(--accent-hover);border-radius:var(--radius-pill);">全部 (5)</button><button class="btn btn-ghost btn-sm">待处理 (2)</button><button class="btn btn-ghost btn-sm">处理中 (2)</button><button class="btn btn-ghost btn-sm">已解决 (1)</button></div>
  674. <table class="tbl"><thead><tr><th>申诉人</th><th>KR</th><th>原评分</th><th>申诉理由</th><th>状态</th><th>处理人</th><th>操作</th></tr></thead><tbody>
  675. <tr><td>周涛</td><td class="text-sm">KR2.1 手术质控标准</td><td class="mono">78</td><td class="text-sm">扣分依据不充分,手术并发症率已下降</td><td><span class="tag tag-warn">待处理</span></td><td>李明</td><td><button class="btn btn-primary btn-sm">处理</button></td></tr>
  676. <tr><td>王芳</td><td class="text-sm">KR1.2 病历规范率</td><td class="mono">60</td><td class="text-sm">系统统计口径有误,未计入12月补录</td><td><span class="tag tag-warn">待处理</span></td><td>李明</td><td><button class="btn btn-primary btn-sm">处理</button></td></tr>
  677. <tr><td>刘洋</td><td class="text-sm">KR3.1 门诊随访率</td><td class="mono">82</td><td class="text-sm">评分标准与Q3不一致</td><td><span class="tag tag-accent">处理中</span></td><td>王主任</td><td><span class="flow"><span class="flow__step flow__step--active">审核中</span></span></td></tr>
  678. <tr><td>陈静</td><td class="text-sm">KR1.3 护理满意度</td><td class="mono">85</td><td class="text-sm">参考数据有误</td><td><span class="tag tag-success">已解决</span></td><td>李明</td><td><button class="btn btn-outline btn-sm">查看</button></td></tr>
  679. </tbody></table>
  680. </div>
  681. </div>
  682. <!-- ── FEEDBACK ────────────────────────────────────────────── -->
  683. <div class="page-panel" id="pg-feedback">
  684. <div class="s-head"><div class="s-head__left"><h2>绩效沟通</h2><p>与上级的反馈对话 · 2025 Q4</p></div><button class="btn btn-outline btn-sm">📅 预约面谈</button></div>
  685. <div class="grid-2" style="grid-template-columns:2fr 1fr;">
  686. <div class="card">
  687. <div class="chat">
  688. <div class="chat__msg chat__msg--out">王主任好,我想约个时间讨论一下 Q4 绩效评分中 KR1.4 的扣分项。<div class="chat__meta">李明 · 12-18 14:30</div></div>
  689. <div class="chat__msg chat__msg--in">好的,明天下午 3 点方便吗?我看了你的申诉材料,病历完整率数据确实有讨论空间。<div class="chat__meta">王主任 · 12-18 15:10</div></div>
  690. <div class="chat__msg chat__msg--out">可以,明天下午 3 点。我会带上 12 月补录记录和系统日志。<div class="chat__meta">李明 · 12-18 15:22</div></div>
  691. <div class="chat__msg chat__msg--ai"><b>🤖 AI 辅助建议</b><br>检测到你在讨论「KR1.4 病历完整率」的评分争议。建议:<br>1. 准备 12 月 EHR 系统操作日志<br>2. 对照同期科室平均值(87%)作为参考<br>3. 引用评分规则 §3.2「数据核实流程」<div class="chat__meta">AI 助手 · 自动生成</div></div>
  692. </div>
  693. <div style="display:flex;gap:8px;margin-top:var(--gap-md);">
  694. <input type="text" placeholder="输入消息..." style="flex:1;padding:10px 14px;border:1px solid var(--border);border-radius:var(--radius-pill);font-size:var(--fs-sm);">
  695. <button class="btn btn-primary btn-sm">发送</button>
  696. </div>
  697. </div>
  698. <div class="card">
  699. <strong style="font-size:var(--fs-body);">沟通历史</strong>
  700. <div class="mt-sm" style="display:flex;flex-direction:column;gap:10px;">
  701. <div style="padding:8px 0;border-bottom:1px solid var(--border-light);"><div class="text-sm" style="font-weight:600;">Q4 中期回顾面谈</div><div class="text-xs text-muted">2025-11-20 · 30 分钟 · 已完成</div></div>
  702. <div style="padding:8px 0;border-bottom:1px solid var(--border-light);"><div class="text-sm" style="font-weight:600;">Q3 绩效结果沟通</div><div class="text-xs text-muted">2025-09-28 · 45 分钟 · 已完成</div></div>
  703. <div style="padding:8px 0;"><div class="text-sm" style="font-weight:600;">Q2 目标对齐讨论</div><div class="text-xs text-muted">2025-06-15 · 20 分钟 · 已完成</div></div>
  704. </div>
  705. </div>
  706. </div>
  707. </div>
  708. <!-- ── PERIODS ─────────────────────────────────────────────── -->
  709. <div class="page-panel" id="pg-periods">
  710. <div class="s-head"><div class="s-head__left"><h2>考核周期</h2><p>管理考核周期与阶段切换</p></div><button class="btn btn-primary btn-sm">+ 新建周期</button></div>
  711. <div class="card mb-md">
  712. <div class="tl">
  713. <div class="tl__item">
  714. <div class="tl__dot tl__dot--done"></div>
  715. <div class="flex-between"><div><div class="tl__title">2025 Q3 · 季度考核</div><div class="tl__desc">2025-07-01 — 2025-09-30</div></div><span class="tag tag-success">已归档</span></div>
  716. <div class="flex-wrap mt-xs"><span class="tag tag-muted">制定</span><span class="tag tag-muted">执行</span><span class="tag tag-muted">评分</span><span class="tag tag-muted">归档</span></div>
  717. </div>
  718. <div class="tl__item">
  719. <div class="tl__dot tl__dot--active"></div>
  720. <div class="flex-between"><div><div class="tl__title">2025 Q4 · 季度考核</div><div class="tl__desc">2025-10-01 — 2025-12-31 · <span class="text-accent">当前周期</span></div></div><span class="tag tag-accent">评分阶段</span></div>
  721. <div class="flex-wrap mt-xs"><span class="tag tag-success">✅ 制定</span><span class="tag tag-success">✅ 执行</span><span class="tag tag-accent">● 评分</span><span class="tag tag-muted">归档</span></div>
  722. </div>
  723. <div class="tl__item">
  724. <div class="tl__dot"></div>
  725. <div class="flex-between"><div><div class="tl__title">2026 Q1 · 季度考核</div><div class="tl__desc">2026-01-01 — 2026-03-31</div></div><span class="tag tag-muted">待开始</span></div>
  726. <div class="flex-wrap mt-xs"><span class="tag tag-muted">制定</span><span class="tag tag-muted">执行</span><span class="tag tag-muted">评分</span><span class="tag tag-muted">归档</span></div>
  727. </div>
  728. </div>
  729. </div>
  730. </div>
  731. <!-- ── TEMPLATES ───────────────────────────────────────────── -->
  732. <div class="page-panel" id="pg-templates">
  733. <div class="s-head"><div class="s-head__left"><h2>绩效模板</h2><p>管理考核模板与评分规则</p></div><button class="btn btn-primary btn-sm">+ 新建模板</button></div>
  734. <div class="grid-2">
  735. <div class="card"><div class="flex-between mb-sm"><span style="font-weight:700;font-size:var(--fs-body);">标准医师 OKR 模板</span><span class="tag tag-accent">默认</span></div><p class="text-sm text-muted">OKR 权重 60% · KPI 权重 40% · 4 维度评分</p><div class="mt-sm"><span class="tag tag-muted">OKR达成</span><span class="tag tag-muted" style="margin-left:4px;">KPI指标</span><span class="tag tag-muted" style="margin-left:4px;">能力评估</span><span class="tag tag-muted" style="margin-left:4px;">价值观</span></div><div class="mt-sm text-xs text-muted">已关联 8 个科室 · 评分公式:加权平均</div></div>
  736. <div class="card"><div class="flex-between mb-sm"><span style="font-weight:700;font-size:var(--fs-body);">护理人员 KPI 模板</span><span class="tag tag-indigo">护理部</span></div><p class="text-sm text-muted">KPI 权重 80% · 能力评估 20% · 3 维度评分</p><div class="mt-sm"><span class="tag tag-muted">护理质量</span><span class="tag tag-muted" style="margin-left:4px;">操作规范</span><span class="tag tag-muted" style="margin-left:4px;">患者反馈</span></div><div class="mt-sm text-xs text-muted">已关联 12 个护理单元 · 评分公式:加权平均</div></div>
  737. <div class="card"><div class="flex-between mb-sm"><span style="font-weight:700;font-size:var(--fs-body);">行政人员 KPI 模板</span></div><p class="text-sm text-muted">KPI 权重 70% · 360° 评估 30%</p><div class="mt-sm"><span class="tag tag-muted">任务完成</span><span class="tag tag-muted" style="margin-left:4px;">协作评价</span><span class="tag tag-muted" style="margin-left:4px;">创新贡献</span></div><div class="mt-sm text-xs text-muted">已关联 5 个部门</div></div>
  738. <div class="card" style="border:2px dashed var(--border);display:flex;align-items:center;justify-content:center;min-height:120px;cursor:pointer;"><span style="color:var(--muted);">+ 新建模板</span></div>
  739. </div>
  740. </div>
  741. <!-- ── DIMENSIONS ──────────────────────────────────────────── -->
  742. <div class="page-panel" id="pg-dimensions">
  743. <div class="s-head"><div class="s-head__left"><h2>考核维度</h2><p>配置评分维度与权重</p></div><button class="btn btn-primary btn-sm">+ 新建维度</button></div>
  744. <div class="grid-2">
  745. <div class="card">
  746. <strong style="font-size:var(--fs-body);">维度列表</strong>
  747. <div style="display:flex;flex-direction:column;gap:8px;margin-top:var(--gap-sm);">
  748. <div class="card card--flat" style="border-left:4px solid var(--accent);display:flex;align-items:center;justify-content:space-between;padding:12px 16px;"><span style="font-weight:600;">OKR 达成</span><span class="tag tag-accent">权重 40%</span></div>
  749. <div class="card card--flat" style="border-left:4px solid var(--dark);display:flex;align-items:center;justify-content:space-between;padding:12px 16px;"><span style="font-weight:600;">KPI 指标</span><span class="tag tag-indigo">权重 30%</span></div>
  750. <div class="card card--flat" style="border-left:4px solid var(--success);display:flex;align-items:center;justify-content:space-between;padding:12px 16px;"><span style="font-weight:600;">能力评估</span><span class="tag tag-success">权重 20%</span></div>
  751. <div class="card card--flat" style="border-left:4px solid var(--orange);display:flex;align-items:center;justify-content:space-between;padding:12px 16px;"><span style="font-weight:600;">价值观</span><span class="tag tag-warn">权重 10%</span></div>
  752. </div>
  753. </div>
  754. <div class="card" style="text-align:center;">
  755. <strong style="font-size:var(--fs-body);">权重分布</strong>
  756. <div style="margin:var(--gap-md) auto;width:160px;height:160px;border-radius:50%;background:conic-gradient(var(--accent) 0% 40%, var(--dark) 40% 70%, var(--success) 70% 90%, var(--orange) 90% 100%);"></div>
  757. <div class="flex-wrap" style="justify-content:center;">
  758. <span style="display:flex;align-items:center;gap:4px;font-size:var(--fs-xs);"><span style="width:10px;height:10px;border-radius:2px;background:var(--accent);display:inline-block;"></span> OKR 40%</span>
  759. <span style="display:flex;align-items:center;gap:4px;font-size:var(--fs-xs);"><span style="width:10px;height:10px;border-radius:2px;background:var(--dark);display:inline-block;"></span> KPI 30%</span>
  760. <span style="display:flex;align-items:center;gap:4px;font-size:var(--fs-xs);"><span style="width:10px;height:10px;border-radius:2px;background:var(--success);display:inline-block;"></span> 能力 20%</span>
  761. <span style="display:flex;align-items:center;gap:4px;font-size:var(--fs-xs);"><span style="width:10px;height:10px;border-radius:2px;background:var(--orange);display:inline-block;"></span> 价值观 10%</span>
  762. </div>
  763. </div>
  764. </div>
  765. </div>
  766. <!-- ── ORG ─────────────────────────────────────────────────── -->
  767. <div class="page-panel" id="pg-org">
  768. <div class="s-head"><div class="s-head__left"><h2>组织架构</h2><p>医院部门与人员结构</p></div><div class="flex-wrap"><input type="text" placeholder="搜索人员..." style="padding:8px 14px;border:1px solid var(--border);border-radius:var(--radius-pill);font-size:var(--fs-sm);width:200px;"></div></div>
  769. <div class="grid-2" style="grid-template-columns:1fr 1fr;">
  770. <div class="card">
  771. <strong style="font-size:var(--fs-body);">部门树</strong>
  772. <ul class="tree mt-sm">
  773. <li><span class="tree__node">🏥 医梦总院</span>
  774. <ul class="tree">
  775. <li><span class="tree__node">🧠 神经内科</span> <span class="text-xs text-muted">12 人</span>
  776. <ul class="tree"><li><span class="tree__leaf">李明 · 主治医师</span></li><li><span class="tree__leaf">张伟 · 副主任医师</span></li><li><span class="tree__leaf">王芳 · 住院医师</span></li></ul>
  777. </li>
  778. <li><span class="tree__node">❤️ 心内科</span> <span class="text-xs text-muted">8 人</span></li>
  779. <li><span class="tree__node">🦴 骨科</span> <span class="text-xs text-muted">6 人</span></li>
  780. <li><span class="tree__node">💊 药剂科</span> <span class="text-xs text-muted">5 人</span></li>
  781. </ul>
  782. </li>
  783. </ul>
  784. </div>
  785. <div class="card">
  786. <strong style="font-size:var(--fs-body);">神经内科成员</strong>
  787. <div class="mt-sm" style="display:flex;flex-direction:column;gap:8px;">
  788. <div class="org-node"><div class="org-node__avatar" style="background:var(--dark);">王</div><div><div class="org-node__name">王建国</div><div class="org-node__role">主任医师 · 科室主任</div></div><span class="tag tag-indigo" style="margin-left:auto;">管理者</span></div>
  789. <div class="org-node"><div class="org-node__avatar" style="background:var(--accent);color:var(--dark);">李</div><div><div class="org-node__name">李明</div><div class="org-node__role">主治医师</div></div></div>
  790. <div class="org-node"><div class="org-node__avatar" style="background:var(--success);">张</div><div><div class="org-node__name">张伟</div><div class="org-node__role">副主任医师</div></div></div>
  791. <div class="org-node"><div class="org-node__avatar" style="background:var(--orange);">王</div><div><div class="org-node__name">王芳</div><div class="org-node__role">住院医师</div></div></div>
  792. <div class="org-node"><div class="org-node__avatar" style="background:var(--red);">赵</div><div><div class="org-node__name">赵丽</div><div class="org-node__role">住院医师</div></div></div>
  793. </div>
  794. </div>
  795. </div>
  796. </div>
  797. <!-- ── NOTIFICATIONS ───────────────────────────────────────── -->
  798. <div class="page-panel" id="pg-notifications">
  799. <div class="s-head"><div class="s-head__left"><h2>消息通知</h2><p>系统通知 · 绩效提醒 · 审批请求</p></div><div class="flex-wrap"><button class="btn btn-outline btn-sm">全部标为已读</button></div></div>
  800. <div class="card">
  801. <div class="flex-wrap mb-sm"><button class="btn btn-sm" style="background:var(--accent-soft);color:var(--accent-hover);border-radius:var(--radius-pill);">全部</button><button class="btn btn-ghost btn-sm">未读 (4)</button><button class="btn btn-ghost btn-sm">系统 (3)</button><button class="btn btn-ghost btn-sm">绩效 (5)</button></div>
  802. <div class="notif notif--unread"><div class="notif__dot"></div><div class="notif__body"><div class="notif__title">绩效评分结果已发布</div><div class="notif__desc">2025 Q4 绩效评分已完成,你的最终得分 86 分(A 级)。点击查看详情。</div></div><span class="notif__time">10 分钟前</span></div>
  803. <div class="notif notif--unread"><div class="notif__dot"></div><div class="notif__body"><div class="notif__title">王芳提交了申诉</div><div class="notif__desc">关于 KR1.2「病历规范率」评分,申诉理由:系统统计口径有误。</div></div><span class="notif__time">1 小时前</span></div>
  804. <div class="notif notif--unread"><div class="notif__dot"></div><div class="notif__body"><div class="notif__title">周期提醒:自评截止还有 2 天</div><div class="notif__desc">2025 Q4 自评提交截止日期为 12 月 20 日,请尽快完成。</div></div><span class="notif__time">3 小时前</span></div>
  805. <div class="notif"><div class="notif__body" style="margin-left:16px;"><div class="notif__title">系统升级通知</div><div class="notif__desc">OKR 系统将于 12 月 25 日凌晨 2:00-4:00 进行维护升级。</div></div><span class="notif__time">昨天</span></div>
  806. <div class="notif"><div class="notif__body" style="margin-left:16px;"><div class="notif__title">张伟提交了 OKR 对齐申请</div><div class="notif__desc">张伟请求将其「手术质控标准」KR 对齐到你的 O2 目标。</div></div><span class="notif__time">昨天</span></div>
  807. <div class="notif"><div class="notif__body" style="margin-left:16px;"><div class="notif__title">绩效沟通预约确认</div><div class="notif__desc">与王主任的面谈已确认:12 月 19 日下午 3:00。</div></div><span class="notif__time">2 天前</span></div>
  808. </div>
  809. </div>
  810. <!-- ── LOGS ────────────────────────────────────────────────── -->
  811. <div class="page-panel" id="pg-logs">
  812. <div class="s-head"><div class="s-head__left"><h2>操作日志</h2><p>系统操作记录 · 最近 30 天</p></div><div class="flex-wrap"><button class="btn btn-outline btn-sm">📥 导出日志</button></div></div>
  813. <div class="card">
  814. <div class="flex-between mb-sm"><div class="flex-wrap"><input type="date" style="padding:6px 12px;border:1px solid var(--border);border-radius:var(--radius-sm);font-size:var(--fs-sm);"> <span class="text-sm text-muted" style="align-self:center;">—</span> <input type="date" style="padding:6px 12px;border:1px solid var(--border);border-radius:var(--radius-sm);font-size:var(--fs-sm);"></div><div class="flex-wrap"><button class="btn btn-sm" style="background:var(--accent-soft);color:var(--accent-hover);border-radius:var(--radius-pill);">全部</button><button class="btn btn-ghost btn-sm">评分</button><button class="btn btn-ghost btn-sm">编辑</button><button class="btn btn-ghost btn-sm">登录</button></div></div>
  815. <table class="tbl"><thead><tr><th>时间</th><th>操作人</th><th>操作类型</th><th>描述</th><th>IP</th></tr></thead><tbody>
  816. <tr><td class="mono text-sm">2025-12-18 15:22</td><td>李明</td><td><span class="tag tag-accent">评分</span></td><td>提交了对张伟的绩效评审</td><td class="mono text-xs">192.168.1.42</td></tr>
  817. <tr><td class="mono text-sm">2025-12-18 14:30</td><td>李明</td><td><span class="tag tag-indigo">编辑</span></td><td>更新了 KR1.4 的进度数据</td><td class="mono text-xs">192.168.1.42</td></tr>
  818. <tr><td class="mono text-sm">2025-12-18 10:15</td><td>王芳</td><td><span class="tag tag-warn">申诉</span></td><td>提交了 KR1.2 评分申诉</td><td class="mono text-xs">192.168.1.88</td></tr>
  819. <tr><td class="mono text-sm">2025-12-18 09:00</td><td>张伟</td><td><span class="tag tag-success">登录</span></td><td>用户登录系统</td><td class="mono text-xs">192.168.1.56</td></tr>
  820. <tr><td class="mono text-sm">2025-12-17 16:40</td><td>王主任</td><td><span class="tag tag-indigo">编辑</span></td><td>修改了 Q4 考核周期截止日期</td><td class="mono text-xs">192.168.1.10</td></tr>
  821. <tr><td class="mono text-sm">2025-12-17 14:20</td><td>李明</td><td><span class="tag tag-accent">评分</span></td><td>完成了对陈静的绩效评审</td><td class="mono text-xs">192.168.1.42</td></tr>
  822. </tbody></table>
  823. <div class="flex-between mt-sm"><span class="text-xs text-muted">共 128 条记录</span><div class="flex-wrap"><button class="btn btn-outline btn-sm" disabled>上一页</button><span class="btn btn-sm" style="background:var(--accent-soft);color:var(--accent-hover);border-radius:var(--radius-sm);">1</span><button class="btn btn-ghost btn-sm">2</button><button class="btn btn-ghost btn-sm">3</button><button class="btn btn-ghost btn-sm">...</button><button class="btn btn-outline btn-sm">下一页</button></div></div>
  824. </div>
  825. </div>
  826. </div><!-- /main -->
  827. </div><!-- /app -->
  828. <script>
  829. const pages = {
  830. login:'登录', workspace:'工作台', 'my-okr':'我的 OKR', 'team-okr':'团队 OKR',
  831. 'okr-align':'OKR 对齐', 'okr-exec':'执行进度', 'my-result':'我的绩效',
  832. 'score-history':'历史绩效', 'scoring-list':'绩效打分', 'scoring-detail':'绩效考评',
  833. appeal:'绩效申诉', feedback:'绩效沟通', periods:'考核周期',
  834. templates:'绩效模板', dimensions:'考核维度', org:'组织架构',
  835. notifications:'消息通知', logs:'操作日志'
  836. };
  837. let cur = 'login';
  838. function navTo(id, el) {
  839. document.getElementById('pg-'+cur).classList.remove('page-panel--active');
  840. document.querySelector('.nav-item--active')?.classList.remove('nav-item--active');
  841. cur = id;
  842. document.getElementById('pg-'+id).classList.add('page-panel--active');
  843. if (el) el.classList.add('nav-item--active');
  844. else document.querySelector('[data-page="'+id+'"]')?.classList.add('nav-item--active');
  845. document.getElementById('topbarTitle').textContent = pages[id] || id;
  846. // Switch login to full-height mode
  847. if (id==='login') {
  848. document.getElementById('pg-login').style.display='flex';
  849. document.querySelector('.topbar').style.display='none';
  850. document.querySelector('.main').style.background='#ffffff';
  851. } else {
  852. document.getElementById('pg-login').style.display='';
  853. document.querySelector('.topbar').style.display='';
  854. document.querySelector('.main').style.background='';
  855. }
  856. }
  857. function toggleMod(id) { document.getElementById(id).classList.toggle('nav-module--collapsed'); }
  858. // Init: login mode hides topbar
  859. document.querySelector('.topbar').style.display='none';
  860. document.querySelector('.main').style.background='#ffffff';
  861. </script>
  862. </body>
  863. </html>