Commit e93ebf16844c57f43863d727121a91fdc431c7f3

Authored by 王彪总
1 parent 5902ef3e

业务线 小程序不用写死,从后端接口获取

Showing 53 changed files with 5068 additions and 2014 deletions
... ... @@ -44,7 +44,7 @@ const checkLoginStatus = () => {
44 44  
45 45 /* 你的全局样式 */
46 46 page {
47   - background-color: #f8f8f8;
  47 + background-color: #F4F6FA;
48 48 height: 100%;
49 49 }
50 50  
... ... @@ -57,9 +57,9 @@ page {
57 57 width: 100%;
58 58 .common-name{
59 59 flex: 1; // 占满剩余空间,挤压标签到右侧
60   - font-size: 28rpx;
  60 + font-size: 32rpx;
61 61 font-weight: 500;
62   - color: #333;
  62 + color: #1F2937;
63 63 // 关键:单行文本溢出省略
64 64 white-space: nowrap;
65 65 overflow: hidden;
... ... @@ -69,13 +69,13 @@ page {
69 69 }
70 70 // 已失效标签样式
71 71 .common-invalid-tag {
72   - color: #f56c6c;
73   - font-size: 24rpx;
  72 + color: #6B7280;
  73 + font-size: 22rpx;
74 74 flex-shrink: 0; // 禁止标签被压缩
75 75 }
76 76 .common-finish-tag{
77   - color: #5ac725;
78   - font-size: 24rpx;
  77 + color: #16A34A;
  78 + font-size: 22rpx;
79 79 flex-shrink: 0; // 禁止标签被压缩
80 80 }
81 81 }
... ... @@ -84,7 +84,7 @@ page {
84 84 }
85 85  
86 86 .u-body-item {
87   - margin-bottom: 16rpx;
  87 + margin-bottom: 6rpx;
88 88 &:last-child {
89 89 margin-bottom: 0;
90 90 }
... ... @@ -107,17 +107,44 @@ page {
107 107  
108 108  
109 109 // 底部按钮样式
  110 +// 底部固定操作栏:全站统一(白底 + 阴影 + 安全区 + 24rpx 左右留白)
110 111 .fixed-bottom-btn-wrap {
111 112 position: fixed;
112 113 bottom: 0;
113 114 left: 0;
114 115 right: 0;
115 116 z-index: 999;
116   - padding: 0;
117   - /* #ifdef MP-WEIXIN */
118   - //padding-bottom: constant(safe-area-inset-bottom);
119   - //padding-bottom: env(safe-area-inset-bottom);
120   - /* #endif */
  117 + box-sizing: border-box;
  118 + padding: 16rpx 24rpx !important;
  119 + padding-bottom: calc(16rpx + env(safe-area-inset-bottom)) !important;
  120 + background-color: #ffffff !important;
  121 + box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06) !important;
  122 +}
  123 +
  124 +// 工单详情等多按钮操作栏:按钮更小更密,保持紧凑内边距
  125 +.fixed-bottom-btn-wrap.order-action-bar {
  126 + padding: 10rpx 14rpx !important;
  127 + padding-bottom: calc(10rpx + env(safe-area-inset-bottom)) !important;
  128 +}
  129 +
  130 +// 底部固定栏主按钮:统一为顶部导航栏同色(pages.json navigationBarBackgroundColor: #2563EB)
  131 +.fixed-bottom-btn-wrap .u-button {
  132 + height: 88rpx !important;
  133 + border-radius: 16rpx !important;
  134 + background-color: #2563EB !important;
  135 + background-image: none !important;
  136 + border-color: #2563EB !important;
  137 +}
  138 +.fixed-bottom-btn-wrap .u-button__text {
  139 + font-size: 30rpx !important;
  140 + font-weight: 500 !important;
  141 +}
  142 +
  143 +// 卡片:uview up-card 与自绘卡片(.form-card / .plan-card)统一圆角与阴影
  144 +.u-card {
  145 + border-radius: 16rpx !important;
  146 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06) !important;
  147 + background-color: #ffffff !important;
121 148 }
122 149 .commonPageLRpadding{
123 150 padding-left: 15px;
... ... @@ -125,8 +152,8 @@ page {
125 152 }
126 153  
127 154 .common-text-color{
128   - font-size: 14px;
129   - color: #606266
  155 + font-size: 26rpx;
  156 + color: #4B5563
130 157 }
131 158  
132 159 // 通用按钮样式(支持任意top值,无需批量生成类名)
... ... @@ -136,7 +163,7 @@ page {
136 163 top: var(--btn-top, 100px);
137 164 right: 15px;
138 165 //transform: translateX(-50%);
139   - background-color: #3c9cff;
  166 + background-color: #2563EB;
140 167 color: #ffffff;
141 168 border: none;
142 169 border-radius: 4px;
... ... @@ -150,20 +177,20 @@ page {
150 177  
151 178 // 点击态
152 179 &:active {
153   - background-color: #2b88ee;
  180 + background-color: #1D4ED8;
154 181 opacity: 0.9;
155 182 }
156 183  
157 184 // 禁用态
158 185 &.disabled {
159   - background-color: #a0c8f5;
  186 + background-color: #93B4F5;
160 187 cursor: not-allowed;
161 188 opacity: 0.7;
162 189 }
163 190 }
164 191  
165   -
166   -
  192 +/* UI 统一规范层(必须放在最后,覆盖上面各页面的旧配色/旧字号) */
  193 +@import "@/common/styles/ui-standard.scss";
167 194  
168 195  
169 196 </style>
170 197 \ No newline at end of file
... ...
api/maintain-manage/maintain-manage.js
... ... @@ -83,7 +83,8 @@ export const maintainPlan= (params) =&gt; {
83 83 * @returns {Promise}
84 84 */
85 85 export const maintainPlanNum= (params) => {
86   - return get('/admin-api/garden/maintain-plan-detail/page',params);
  86 + // 走 app-api:后端按登录用户的部门 + 角色过滤批次,并返回进行中的 commitId(结束任务要用)
  87 + return get('/app-api/app/garden/maintain-plan-detail/page',params);
87 88 };
88 89  
89 90  
... ...
common/config/env.js
... ... @@ -2,12 +2,12 @@
2 2 const env = {
3 3 // 开发环境
4 4 development: {
5   - baseUrl: 'https://test.jichengshanshui.com.cn:28302',
  5 + // baseUrl: 'https://test.jichengshanshui.com.cn:28302',
6 6 // https://test.jichengshanshui.com.cn:28302
7 7  
8   - // baseUrl: 'http://192.168.1.111:48081',
  8 + baseUrl: 'http://192.168.1.163:48081',
9 9  
10   - uploadUrl: 'https://test.jichengshanshui.com.cn:28302',
  10 + uploadUrl: 'http://192.168.1.163:48081',
11 11 // baseApi:'admin-api',
12 12 // appApi:'app-api'
13 13 },
... ...
common/styles/ui-standard.scss 0 → 100644
  1 +/* ==========================================================================
  2 + * JCSS 小程序 · UI 统一规范层
  3 + * --------------------------------------------------------------------------
  4 + * 依据:jcss-mp-design/index.html(42 页设计稿,1px = 2rpx)
  5 + * 引入:App.vue 全局 style(非 scoped),一处改动全站生效
  6 + * 约束:只定义样式;不涉及任何 JS / 接口 / 状态判断 / 点击事件 / 数据渲染
  7 + * ========================================================================== */
  8 +
  9 +/* ==========================================================================
  10 + * 1. 设计令牌(与设计稿 :root 变量一一对应,px × 2 = rpx)
  11 + * ========================================================================== */
  12 +/* --- 1.1 品牌色 --- */
  13 +$j-brand: #2563EB;
  14 +$j-brand-a: #1D4ED8;
  15 +$j-brand-light: #EBF3FF;
  16 +
  17 +/* --- 1.2 操作语义色:严格绑定按钮类型 --- */
  18 +$j-approve: #16A34A; // 审批通过 · 绿
  19 +$j-assign: #2563EB; // 分配 / 转派 / 详情 · 蓝
  20 +$j-return: #D97706; // 退回 · 橙
  21 +$j-reject: #DC2626; // 驳回 / 危险操作 · 红
  22 +$j-neutral: #6B7280; // 撤回 / 次要 · 灰
  23 +$j-doing: #0891B2; // 进行中 · 青
  24 +
  25 +/* --- 1.2.1 操作按钮色板(列表 / 详情卡片按钮,按设计稿 94 取色) --- */
  26 +$j-btn-primary: #3B9DFF; // 分配 / 详情 · 亮蓝
  27 +$j-btn-primary-a: #2E8AE6;
  28 +$j-btn-success: #078D0A; // 审批通过 / 实施 / 结束 · 深绿
  29 +$j-btn-success-a: #066B08;
  30 +$j-btn-warning: #F9AE3D; // 退回 · 琥珀
  31 +$j-btn-warning-a: #E39A2C;
  32 +$j-btn-danger: #F56C6C; // 驳回 / 危险操作 · 柔红
  33 +$j-btn-danger-a: #E05959;
  34 +$j-btn-info: #909399; // 撤回 / 次要 · 灰
  35 +$j-btn-info-a: #7D8085;
  36 +$j-btn-transfer: #0891B2; // 转办 / 转派 · 青
  37 +$j-btn-transfer-a: #077A96;
  38 +
  39 +/* --- 1.3 语义底色(标签 / 提示条) --- */
  40 +$j-approve-bg: #EAF7EF;
  41 +$j-assign-bg: #EBF3FF;
  42 +$j-return-bg: #FDF4E7;
  43 +$j-reject-bg: #FDECEC;
  44 +$j-neutral-bg: #F4F5F7;
  45 +$j-doing-bg: #E6F6FA;
  46 +
  47 +/* --- 1.4 点击态:同色系明暗微调,不换主色 --- */
  48 +$j-approve-a: #12833C;
  49 +$j-assign-a: #1D4ED8;
  50 +$j-return-a: #B96504;
  51 +$j-reject-a: #B91C1C;
  52 +$j-neutral-a: #565E6B;
  53 +
  54 +/* --- 1.5 文本色 --- */
  55 +$j-text-title: #1F2937; // 卡片主标题
  56 +$j-text-label: #9CA3AF; // 标签(浅灰)
  57 +$j-text-value: #4B5563; // 内容值
  58 +$j-text-weak: #9CA3AF; // 辅助说明
  59 +$j-text-strong: #1F2937; // 强调值
  60 +
  61 +/* --- 1.6 字号层级(全站 6 档) --- */
  62 +$j-fs-title: 32rpx; // 16px 卡片主标题
  63 +$j-fs-lg: 30rpx; // 15px 次级标题
  64 +$j-fs-label: 26rpx; // 13px 标签 / 内容值
  65 +$j-fs-value: 26rpx; // 13px 内容值
  66 +$j-fs-btn: 24rpx; // 12px 按钮文字
  67 +$j-fs-tip: 22rpx; // 11px 标签 / 辅助说明
  68 +
  69 +/* --- 1.7 间距 --- */
  70 +$j-sp-xs: 8rpx; // 4px
  71 +$j-sp-sm: 16rpx; // 8px
  72 +$j-sp-md: 24rpx; // 12px
  73 +$j-sp-lg: 32rpx; // 16px
  74 +$j-gap-item: 6rpx; // 3px 信息行之间
  75 +$j-gap-btn: 16rpx; // 8px 按钮之间
  76 +$j-page-pad: 24rpx; // 12px 页面内边距
  77 +$j-card-pad: 24rpx; // 12px 卡片内边距
  78 +
  79 +/* --- 1.8 容器色 --- */
  80 +$j-bg: #F4F6FA; // 页面底
  81 +$j-card: #ffffff; // 卡片
  82 +$j-line: #E8EBF0; // 分隔线
  83 +$j-block: #F4F6FA; // 弱区块 / 次级标签底
  84 +
  85 +/* --- 1.9 圆角(4px / 8px / 12px / 胶囊) --- */
  86 +$j-r-btn: 8rpx;
  87 +$j-r-card: 16rpx;
  88 +$j-r-lg: 24rpx;
  89 +$j-r-pill: 999rpx;
  90 +
  91 +/* --- 1.10 阴影 --- */
  92 +$j-shadow-card: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  93 +$j-shadow-float: 0 -8rpx 28rpx rgba(17, 24, 39, 0.08);
  94 +
  95 +/* ==========================================================================
  96 + * 2. 信息项:标签自然宽 + 值右对齐(设计稿 .kv)
  97 + * --------------------------------------------------------------------------
  98 + * 设计稿不固定标签列宽:标签浅灰靠左,值占满剩余宽度并右对齐,
  99 + * 因此各行内容值的右边缘天然对齐,不会参差不齐。
  100 + * ========================================================================== */
  101 +.u-body-item {
  102 + display: flex !important;
  103 + align-items: flex-start !important;
  104 + gap: $j-sp-sm !important;
  105 + margin-bottom: $j-gap-item !important;
  106 +
  107 + &:last-child {
  108 + margin-bottom: 0 !important;
  109 + }
  110 +}
  111 +
  112 +/* 单行信息项(带 common-item-center)仍按垂直居中排版 */
  113 +.u-body-item.common-item-center {
  114 + align-items: center !important;
  115 +}
  116 +
  117 +.u-body-item-title {
  118 + flex: 0 0 auto !important;
  119 + width: auto !important;
  120 + min-width: 0 !important;
  121 + font-size: $j-fs-label !important;
  122 + font-weight: 400 !important;
  123 + color: $j-text-label !important;
  124 + line-height: 1.5 !important;
  125 + white-space: nowrap;
  126 +}
  127 +
  128 +.u-body-value {
  129 + flex: 1 1 auto;
  130 + min-width: 0;
  131 + font-size: $j-fs-value !important;
  132 + font-weight: 400 !important;
  133 + color: $j-text-value !important;
  134 + line-height: 1.5 !important;
  135 + text-align: right;
  136 + word-break: break-all;
  137 +}
  138 +
  139 +/* 卡片主标题:比信息项高一级 */
  140 +.common-card-list .common-name,
  141 +.card-header .common-name,
  142 +.common-card-title {
  143 + font-size: $j-fs-title !important;
  144 + font-weight: 500 !important;
  145 + color: $j-text-title !important;
  146 + line-height: 1.4 !important;
  147 +}
  148 +
  149 +/* ==========================================================================
  150 + * 3. 操作按钮:五类语义色 + 统一尺寸(含三套现有实现)
  151 + * --------------------------------------------------------------------------
  152 + * task-btn:列表卡按钮 order-action-btn:详情底部按钮
  153 + * 均为 56rpx 高(28px)/ 24rpx 白字 / 8rpx 圆角,文字过长省略不换行
  154 + * ========================================================================== */
  155 +.task-btn,
  156 +.order-action-btn {
  157 + box-sizing: border-box;
  158 + height: 56rpx;
  159 + line-height: 56rpx;
  160 + padding: 0 24rpx;
  161 + border-radius: $j-r-btn;
  162 + font-size: $j-fs-btn !important;
  163 + font-weight: 400;
  164 + color: #ffffff !important; // 按钮内文字统一白色
  165 + text-align: center !important;
  166 + white-space: nowrap;
  167 + overflow: hidden;
  168 + text-overflow: ellipsis;
  169 + transition: background-color 0.15s ease;
  170 +}
  171 +
  172 +// 亮蓝:详情等次要主操作
  173 +.task-btn--primary,
  174 +.order-action-btn--primary {
  175 + background-color: $j-btn-primary !important;
  176 +
  177 + &:active {
  178 + background-color: $j-btn-primary-a !important;
  179 + }
  180 +}
  181 +
  182 +// 深蓝:分配(卡片主操作,比「详情」深一级)
  183 +.task-btn--assign,
  184 +.order-action-btn--assign {
  185 + background-color: $j-assign !important;
  186 +
  187 + &:active {
  188 + background-color: $j-assign-a !important;
  189 + }
  190 +}
  191 +
  192 +// 深绿:审批通过 / 实施 / 结束
  193 +.task-btn--success,
  194 +.order-action-btn--success {
  195 + background-color: $j-btn-success !important;
  196 +
  197 + &:active {
  198 + background-color: $j-btn-success-a !important;
  199 + }
  200 +}
  201 +
  202 +// 琥珀:退回
  203 +.task-btn--warning,
  204 +.order-action-btn--warning {
  205 + background-color: $j-btn-warning !important;
  206 +
  207 + &:active {
  208 + background-color: $j-btn-warning-a !important;
  209 + }
  210 +}
  211 +
  212 +// 青:转办 / 转派
  213 +.task-btn--transfer,
  214 +.order-action-btn--transfer {
  215 + background-color: $j-btn-transfer !important;
  216 +
  217 + &:active {
  218 + background-color: $j-btn-transfer-a !important;
  219 + }
  220 +}
  221 +
  222 +// 红:驳回 / 危险操作
  223 +.task-btn--error,
  224 +.order-action-btn--error {
  225 + background-color: $j-btn-danger !important;
  226 +
  227 + &:active {
  228 + background-color: $j-btn-danger-a !important;
  229 + }
  230 +}
  231 +
  232 +// 灰:撤回 / 次要
  233 +.task-btn--info,
  234 +.order-action-btn--info {
  235 + background-color: $j-btn-info !important;
  236 +
  237 + &:active {
  238 + background-color: $j-btn-info-a !important;
  239 + }
  240 +}
  241 +
  242 +/* ==========================================================================
  243 + * 4. 按钮行:auto-fit 自适应换行
  244 + * --------------------------------------------------------------------------
  245 + * 原实现为 grid repeat(var(--cols)),列数由 JS 算出(最多 5 列),
  246 + * 按钮多时被压窄溢出。改为 auto-fit 后由容器宽度决定每行个数:
  247 + * 5 个 → 3+2 两行;3 个 → 一行等分;2 个 → 各占一半;1 个 → 独占一行
  248 + * JS 传入的 --cols 自动失效(仅样式层变化,不改 JS)。
  249 + * ========================================================================== */
  250 +.task-btn-row,
  251 +.order-action-row {
  252 + display: grid !important;
  253 + grid-template-columns: repeat(auto-fit, minmax(144rpx, 1fr)) !important;
  254 + gap: $j-gap-btn !important;
  255 + margin-bottom: 0 !important;
  256 +}
  257 +
  258 +.task-btn-row > view,
  259 +.order-action-row > view {
  260 + min-width: 0; // 防止长文案撑破栅格
  261 +}
  262 +
  263 +/* ==========================================================================
  264 + * 5. 通用绝对定位按钮(历史实现,仅保留配色,新页面改用 .card-action-row)
  265 + * ========================================================================== */
  266 +.common-custom-btn {
  267 + background-color: $j-assign !important;
  268 + color: #ffffff !important;
  269 + border-radius: $j-r-btn !important;
  270 + padding: 8rpx 24rpx !important;
  271 + font-size: $j-fs-btn !important;
  272 + line-height: 1.4;
  273 + text-align: center;
  274 + white-space: nowrap;
  275 + transition: background-color 0.15s ease;
  276 +
  277 + &:active {
  278 + background-color: $j-assign-a !important;
  279 + }
  280 +
  281 + &.disabled {
  282 + background-color: #93B4F5 !important;
  283 + opacity: 0.7;
  284 + }
  285 +}
  286 +
  287 +/* ==========================================================================
  288 + * 5.1 卡片内按钮语义化(设计稿 .btn.sm / .btn-link)
  289 + * --------------------------------------------------------------------------
  290 + * 主操作 = 蓝底白字 / 次要操作 = 白底描边 / 危险操作 = 红色文字
  291 + * 尺寸:高 56rpx(28px) · 字号 24rpx(12px) · 圆角 8rpx(4px) · 左右 24rpx
  292 + * ========================================================================== */
  293 +.mini-btn {
  294 + box-sizing: border-box;
  295 + display: flex;
  296 + align-items: center;
  297 + justify-content: center;
  298 + min-width: 120rpx;
  299 + height: 56rpx;
  300 + padding: 0 $j-sp-md;
  301 + font-size: $j-fs-btn !important;
  302 + font-weight: 400;
  303 + color: #ffffff !important;
  304 + text-align: center !important;
  305 + border-radius: $j-r-btn;
  306 + flex-shrink: 0;
  307 + white-space: nowrap;
  308 + transition: background-color 0.15s ease;
  309 +}
  310 +
  311 +.mini-btn--primary {
  312 + background-color: $j-assign !important;
  313 +
  314 + &:active {
  315 + background-color: $j-assign-a !important;
  316 + }
  317 +}
  318 +
  319 +.mini-btn--info {
  320 + background-color: $j-neutral !important;
  321 +
  322 + &:active {
  323 + background-color: $j-neutral-a !important;
  324 + }
  325 +}
  326 +
  327 +/* 次要操作:白底描边,与主操作同一行时形成主次对比 */
  328 +.mini-btn--plain {
  329 + color: $j-text-value !important;
  330 + background-color: #ffffff !important;
  331 + border: 1rpx solid $j-line;
  332 +
  333 + &:active {
  334 + background-color: $j-block !important;
  335 + }
  336 +}
  337 +
  338 +/* 置为失效 / 删除类危险操作:红色文字按钮,占位与普通按钮一致 */
  339 +.btn-text-danger,
  340 +.btn-set-invalid {
  341 + flex-shrink: 0;
  342 + padding: 8rpx 0;
  343 + font-size: $j-fs-label !important;
  344 + font-weight: 400;
  345 + color: $j-reject !important;
  346 + line-height: 1.4;
  347 + white-space: nowrap;
  348 + transition: color 0.15s ease;
  349 +
  350 + &:active {
  351 + color: $j-reject-a !important;
  352 + opacity: 0.8;
  353 + }
  354 +}
  355 +
  356 +/* ==========================================================================
  357 + * 6. 详情页统一:u-cell 排版收口(设计稿 .card.pad + .kv)
  358 + * --------------------------------------------------------------------------
  359 + * 三类工单(养护 / 区域 / AI)详情都用 up-cell 渲染字段,此处统一层级:
  360 + * 标签 26rpx #9CA3AF 左 / 内容值 26rpx #4B5563 右 / 行内 16rpx 上下
  361 + * 注意:uview-plus 单元格内部类名为 u-cell__xxx(组件内为 scoped 样式),
  362 + * 全局层必须带 !important 才生效。
  363 + * ========================================================================== */
  364 +.u-cell__body {
  365 + display: flex !important;
  366 + justify-content: space-between !important;
  367 + padding: 16rpx $j-card-pad !important;
  368 +}
  369 +
  370 +/* 单元格之间的分隔线沿用 uview 的 u-line,仅去掉卡片最后一行的尾线 */
  371 +.u-cell-group__wrapper > .u-cell:last-child .u-line {
  372 + display: none !important;
  373 +}
  374 +
  375 +.u-cell__title-text,
  376 +.u-cell__label {
  377 + font-size: $j-fs-label !important;
  378 + font-weight: 400 !important;
  379 + color: $j-text-label !important;
  380 + line-height: 1.5 !important;
  381 +}
  382 +
  383 +/* 标题插槽(#title 自定义 view)同样收到「标签」层级 */
  384 +.u-cell__title > view {
  385 + font-size: $j-fs-label !important;
  386 + font-weight: 400 !important;
  387 + color: $j-text-label !important;
  388 + line-height: 1.5 !important;
  389 +}
  390 +
  391 +.u-cell__value {
  392 + font-size: $j-fs-value !important;
  393 + font-weight: 400 !important;
  394 + color: $j-text-value !important;
  395 + line-height: 1.5 !important;
  396 + text-align: right !important;
  397 + word-break: break-all;
  398 +}
  399 +
  400 +/* 插槽内的内容值统一走 .common-text-color(App.vue 中定义为 #4B5563) */
  401 +
  402 +/* 信息区块统一成卡片:四周留白一致,标题/内容与边框保持固定间距 */
  403 +.u-cell-group {
  404 + box-sizing: border-box;
  405 + margin: 0 $j-page-pad $j-sp-md !important;
  406 + border-radius: $j-r-card;
  407 + overflow: hidden;
  408 + background-color: $j-card;
  409 +}
  410 +
  411 +/* 级联选择器弹层内的单元格保持原样(多列并排,不能加外边距) */
  412 +.area-item .u-cell-group {
  413 + margin: 0 !important;
  414 + border-radius: 0;
  415 + background-color: transparent;
  416 +}
  417 +
  418 +/* 「我的」页单元格本来就在白色圆角面板内,不再叠加卡片外框 */
  419 +.mine-content .u-cell-group {
  420 + margin-left: 0 !important;
  421 + margin-right: 0 !important;
  422 + border-radius: 0;
  423 +}
  424 +
  425 +/* 详情页附图区块:与上方信息卡同宽同圆角,避免出现整宽的白色通栏 */
  426 +.img-tabs-block {
  427 + margin: 0 $j-page-pad $j-sp-md;
  428 + border-radius: $j-r-card;
  429 + overflow: hidden;
  430 +}
  431 +
  432 +/* ==========================================================================
  433 + * 6.1 卡片内的操作区(设计稿 .tcard-foot)
  434 + * --------------------------------------------------------------------------
  435 + * 操作按钮不再用绝对定位悬浮在卡片上,统一收进底部操作区:
  436 + * 上方 16rpx 留白 + 1rpx 分隔线,按钮右对齐,间距 16rpx
  437 + * ========================================================================== */
  438 +.card-action-row {
  439 + display: flex;
  440 + align-items: center;
  441 + justify-content: flex-end;
  442 + gap: $j-gap-btn;
  443 + margin-top: $j-sp-sm;
  444 + padding-top: $j-sp-sm;
  445 + border-top: 1rpx solid $j-line;
  446 +}
  447 +
  448 +/* ==========================================================================
  449 + * 7. 状态标签(设计稿 .tag:高 40rpx / 字号 22rpx / 圆角 8rpx / 左右 16rpx)
  450 + * ========================================================================== */
  451 +.urgency-tag,
  452 +.common-invalid-tag,
  453 +.common-finish-tag,
  454 +.common-pending-tag,
  455 +.common-timeout-tag,
  456 +.status-tag {
  457 + display: inline-flex !important;
  458 + align-items: center !important;
  459 + flex-shrink: 0;
  460 + height: 40rpx;
  461 + padding: 0 $j-sp-sm;
  462 + font-size: $j-fs-tip !important;
  463 + font-weight: 500;
  464 + border-radius: $j-r-btn;
  465 + line-height: 1;
  466 + white-space: nowrap;
  467 +}
  468 +
  469 +/* 待完成:浅蓝底蓝字 */
  470 +.common-pending-tag {
  471 + background-color: $j-assign-bg !important;
  472 + color: $j-assign !important;
  473 +}
  474 +
  475 +/* 已完成:浅绿底绿字 */
  476 +.common-finish-tag {
  477 + background-color: $j-approve-bg !important;
  478 + color: $j-approve !important;
  479 +}
  480 +
  481 +/* 已失效:灰底灰字(设计稿 invalid 为中性灰,不是红色) */
  482 +.common-invalid-tag {
  483 + background-color: $j-neutral-bg !important;
  484 + color: $j-neutral !important;
  485 +}
  486 +
  487 +/* 超时:浅红底红字 */
  488 +.common-timeout-tag {
  489 + background-color: $j-reject-bg !important;
  490 + color: $j-reject !important;
  491 +}
  492 +
  493 +/* ==========================================================================
  494 + * 8. 全局文本基线
  495 + * ========================================================================== */
  496 +page {
  497 + font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
  498 + font-size: $j-fs-value;
  499 + color: $j-text-title;
  500 + line-height: 1.5;
  501 + -webkit-font-smoothing: antialiased;
  502 + -webkit-text-size-adjust: 100%;
  503 + background-color: $j-bg;
  504 +}
  505 +
  506 +/* ==========================================================================
  507 + * 9. Tab 组件统一
  508 + * ========================================================================== */
  509 +.u-tabs__wrapper__nav__line {
  510 + background-color: $j-brand !important;
  511 +}
  512 +
  513 +.u-tabs__wrapper__nav__item__text {
  514 + font-size: 28rpx !important; // 设计稿 tab 字号 14px
  515 +}
  516 +
  517 +/* --- 9.1 首页下划线式一级 Tab --- */
  518 +.main-tab-item {
  519 + font-size: $j-fs-lg;
  520 + color: $j-text-value;
  521 + font-weight: 400;
  522 +
  523 + &.active {
  524 + color: $j-brand;
  525 + font-weight: 500;
  526 +
  527 + &::after {
  528 + background-color: $j-brand;
  529 + }
  530 + }
  531 +}
  532 +
  533 +/* --- 9.2 胶囊 Tab --- */
  534 +.tab-capsule {
  535 + font-size: $j-fs-label;
  536 + color: $j-text-weak;
  537 + background-color: $j-block;
  538 + border-radius: $j-r-btn;
  539 +
  540 + &.active {
  541 + color: $j-brand;
  542 + background-color: $j-brand-light;
  543 + }
  544 +}
  545 +
  546 +/* ==========================================================================
  547 + * 9.3 搜索条(设计稿 .search-bar / .sbox)
  548 + * --------------------------------------------------------------------------
  549 + * u-search 在 animation=true 时右侧「搜索」宽度为 0,只在输入框聚焦后才展开;
  550 + * 设计稿要求常显,这里用样式补回宽度与间距,不修改组件 props。
  551 + * 圆角按设计稿做成圆角矩形(8px),不是左右全圆的胶囊。
  552 + * ========================================================================== */
  553 +.u-search__content {
  554 + border-radius: $j-r-card !important;
  555 +}
  556 +
  557 +.u-search__action {
  558 + width: 40px !important;
  559 + margin-left: $j-sp-sm !important;
  560 + font-size: $j-fs-label !important;
  561 + color: $j-brand !important;
  562 +}
  563 +
  564 +/* ==========================================================================
  565 + * 10. 弹层收起兜底:过渡层不拦截点击
  566 + * --------------------------------------------------------------------------
  567 + * uview-plus 的 u-transition 把 mergeStyle 里的 display:none 注释掉了,
  568 + * 收起动画结束后要等 setTimeout(onTransitionEnd) 才真正移除节点。
  569 + * u-popup 的遮罩是 position:fixed + z-index 10075 的全屏层,收起时透明度
  570 + * 已降为 0,一旦该定时器被页面重渲染打断,就会残留一个「看不见但吃点击」
  571 + * 的透明层,表现为页面正常显示、所有按钮却都点不动。
  572 + * 这里让处于收起动画的过渡层不接收点击:无功能变化(300ms 收起期间本来
  573 + * 也不该再点下层),但可以彻底消除上述残留遮挡。
  574 + * ========================================================================== */
  575 +.u-transition.u-fade-leave-active,
  576 +.u-transition.u-fade-up-leave-active,
  577 +.u-transition.u-fade-down-leave-active,
  578 +.u-transition.u-fade-left-leave-active,
  579 +.u-transition.u-fade-right-leave-active,
  580 +.u-transition.u-fade-zoom-leave-active,
  581 +.u-transition.u-slide-up-leave-active,
  582 +.u-transition.u-slide-down-leave-active,
  583 +.u-transition.u-slide-left-leave-active,
  584 +.u-transition.u-slide-right-leave-active,
  585 +.u-transition.u-zoom-leave-active {
  586 + pointer-events: none !important;
  587 +}
... ...
common/utils/common.js
... ... @@ -105,7 +105,14 @@ export const buzStatusMap = {
105 105 * 工作流节点动作按钮颜色(与统一动作弹窗保持一致)
106 106 * @param {string} code - 动作编码,如 ASSIGN/REJECT/RETURN_PREV
107 107 */
108   -export const getActionButtonType = (code) => {
  108 +export const getActionButtonType = (code, name) => {
  109 + // 名称优先:部分流程把「退回」配成了 COMPLETE 编码,只看编码会渲染成绿色
  110 + const text = name || ''
  111 + if (text.includes('驳回') || text.includes('拒绝')) return 'error'
  112 + if (text.includes('退回') || text.includes('回退') || text.includes('不通过')) return 'warning'
  113 + if (text.includes('转办') || text.includes('转派') || text.includes('转交')) return 'transfer'
  114 + // 分配是卡片主操作:用比「详情」更深的品牌蓝
  115 + if (code === 'ASSIGN' || text.includes('分配') || text.includes('指派')) return 'assign'
109 116 switch (code) {
110 117 case 'APPROVE':
111 118 case 'HANDLE':
... ... @@ -124,6 +131,17 @@ export const getActionButtonType = (code) =&gt; {
124 131 }
125 132  
126 133 /**
  134 + * 操作按钮行每行按钮数:单个按钮占一半宽度(左对齐),多个按钮等分,最多 5 个一行
  135 + * @param {number} count - 按钮总数
  136 + * @returns {number} 栅格列数
  137 + */
  138 +export const getActionRowCols = (count) => {
  139 + const total = Number(count) || 0
  140 + // 1 个按钮时用 2 列,按钮占 1 列即页面一半
  141 + return total <= 1 ? 2 : Math.min(total, 5)
  142 +}
  143 +
  144 +/**
127 145 * 计算两个时间的时间差,返回格式化字符串(天/小时/分钟/秒,按需显示,无无效单位)
128 146 * @param {string | Date | number} startTime - 开始时间(时间字符串/Date对象/10位/13位时间戳)
129 147 * @param {string | Date | number} endTime - 结束时间(时间字符串/Date对象/10位/13位时间戳)
... ...
components/grouped-picker/grouped-picker.vue
... ... @@ -35,8 +35,8 @@
35 35 @change="onTabChange"
36 36 :lineWidth="30"
37 37 :lineHeight="4"
38   - activeColor="#2979ff"
39   - lineColor="#2979ff"
  38 + activeColor="#2563EB"
  39 + lineColor="#2563EB"
40 40 inactiveColor="#606266"
41 41 >
42 42 </up-tabs>
... ... @@ -92,7 +92,7 @@
92 92 </view>
93 93 <!-- 单选:原型没覆盖,右侧给一个选中标记 -->
94 94 <view v-else-if="!multiple" class="gp-radio">
95   - <up-icon v-if="isSelected(row)" name="checkmark" size="16" color="#2979ff"></up-icon>
  95 + <up-icon v-if="isSelected(row)" name="checkmark" size="16" color="#2563EB"></up-icon>
96 96 </view>
97 97 </view>
98 98 </view>
... ... @@ -487,9 +487,9 @@ watch(
487 487 height: 28rpx;
488 488 padding: 0 6rpx;
489 489 border-radius: 14rpx;
490   - background: #2979ff;
  490 + background: #2563EB;
491 491 color: #ffffff;
492   - font-size: 20rpx;
  492 + font-size: 24rpx;
493 493 line-height: 28rpx;
494 494 text-align: center;
495 495 }
... ... @@ -537,8 +537,8 @@ watch(
537 537 justify-content: center;
538 538  
539 539 &.is-checked {
540   - background: #2979ff;
541   - border-color: #2979ff;
  540 + background: #2563EB;
  541 + border-color: #2563EB;
542 542 }
543 543 }
544 544  
... ... @@ -562,7 +562,7 @@ watch(
562 562  
563 563 .gp-row-crumb {
564 564 margin-top: 4rpx;
565   - font-size: 22rpx;
  565 + font-size: 24rpx;
566 566 color: #909399;
567 567 }
568 568  
... ... @@ -609,7 +609,7 @@ watch(
609 609  
610 610 .gp-empty {
611 611 padding: 60rpx 0;
612   - font-size: 26rpx;
  612 + font-size: 28rpx;
613 613 color: #c0c4cc;
614 614 text-align: center;
615 615 }
... ...
components/my-cascader/my-cascader.vue
... ... @@ -337,10 +337,10 @@ onMounted(() =&gt; {
337 337 }
338 338 .trigger-text {
339 339 font-size: 28rpx;
340   - color: #333;
  340 + color: #1a1a1a;
341 341 }
342 342 .trigger-icon {
343   - color: #999;
  343 + color: #909399;
344 344 }
345 345  
346 346 .area-box {
... ...
components/unified-task-actions/unified-task-actions.vue
... ... @@ -4,6 +4,7 @@
4 4 mode="bottom"
5 5 round
6 6 closeable
  7 + bg-color="#F4F6FA"
7 8 :safe-area-inset-bottom="true"
8 9 @close="close"
9 10 >
... ... @@ -15,7 +16,7 @@
15 16 <up-button
16 17 v-for="action in actions"
17 18 :key="action.code"
18   - :type="getButtonType(action.code)"
  19 + :type="getButtonType(action.code, action.name)"
19 20 size="large"
20 21 :customStyle="{ marginBottom: '20rpx' }"
21 22 @click="selectAction(action)"
... ... @@ -28,7 +29,10 @@
28 29 <!-- 第二步:动作表单 -->
29 30 <view v-else class="unified-action-form">
30 31 <view v-if="current.requireAssignee" class="form-item">
31   - <view class="form-label">处理人</view>
  32 + <view class="sec-head">
  33 + <view class="sec-bar"></view>
  34 + <view class="form-label">处理人</view>
  35 + </view>
32 36 <up-radio-group v-if="workers.length" v-model="form.nextAssignee" class="worker-list">
33 37 <up-radio
34 38 v-for="worker in workers"
... ... @@ -43,7 +47,10 @@
43 47 </view>
44 48  
45 49 <view class="form-item">
46   - <view class="form-label">{{ reasonLabel }}</view>
  50 + <view class="sec-head">
  51 + <view class="sec-bar"></view>
  52 + <view class="form-label">{{ reasonLabel }}</view>
  53 + </view>
47 54 <up-textarea
48 55 v-model.trim="form.reason"
49 56 :placeholder="reasonPlaceholder"
... ... @@ -54,7 +61,10 @@
54 61 </view>
55 62  
56 63 <view v-if="current.requireAttachment" class="form-item">
57   - <view class="form-label">附件(必填)</view>
  64 + <view class="sec-head">
  65 + <view class="sec-bar"></view>
  66 + <view class="form-label">附件(必填)</view>
  67 + </view>
58 68 <up-upload
59 69 :file-list="attachImgs.rawImgList.value || []"
60 70 @after-read="attachImgs.uploadImgs"
... ... @@ -181,8 +191,12 @@ const backToList = () =&gt; {
181 191 current.value = null
182 192 }
183 193  
184   -/** 动作按钮颜色 */
185   -const getButtonType = (code) => {
  194 +/** 动作按钮颜色:名称优先(部分流程「退回」用的是 COMPLETE 编码) */
  195 +const getButtonType = (code, name) => {
  196 + const text = name || ''
  197 + if (text.includes('驳回') || text.includes('拒绝')) return 'error'
  198 + if (text.includes('退回') || text.includes('回退') || text.includes('不通过')) return 'warning'
  199 + if (text.includes('转办') || text.includes('转派') || text.includes('转交')) return 'info'
186 200 switch (code) {
187 201 case 'APPROVE':
188 202 case 'HANDLE':
... ... @@ -285,17 +299,20 @@ defineExpose({ open })
285 299 </script>
286 300  
287 301 <style lang="scss" scoped>
  302 +// 弹窗内容:浅灰底(由 up-popup 的 bg-color 控制),左右 24rpx
288 303 .unified-action-popup {
289   - padding: 40rpx 40rpx calc(40rpx + env(safe-area-inset-bottom));
  304 + padding: 32rpx 24rpx calc(40rpx + env(safe-area-inset-bottom));
290 305 max-height: 80vh;
291 306 overflow-y: auto;
  307 + box-sizing: border-box;
292 308 }
293 309  
294 310 .unified-action-title {
295   - font-size: 34rpx;
296   - font-weight: bold;
  311 + font-size: 32rpx;
  312 + font-weight: 500;
  313 + color: #1F2937;
297 314 text-align: center;
298   - margin-bottom: 40rpx;
  315 + margin-bottom: 24rpx;
299 316 }
300 317  
301 318 .unified-action-list {
... ... @@ -304,34 +321,103 @@ defineExpose({ open })
304 321 }
305 322  
306 323 .unified-action-tip {
307   - color: #909399;
308   - font-size: 26rpx;
  324 + color: #9CA3AF;
  325 + font-size: 28rpx;
309 326 padding: 20rpx 0;
310 327 }
311 328  
  329 +// 表单分区:白色卡片(设计稿 .card)
312 330 .unified-action-form .form-item {
313   - margin-bottom: 30rpx;
  331 + margin-bottom: 24rpx;
  332 + padding: 8rpx 24rpx 24rpx;
  333 + background-color: #ffffff;
  334 + border-radius: 16rpx;
  335 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  336 +}
  337 +
  338 +// 区块标题:蓝色竖条 + 标题(设计稿 .card-title)
  339 +.sec-head {
  340 + display: flex;
  341 + align-items: center;
  342 + gap: 12rpx;
  343 + padding: 20rpx 0 8rpx;
  344 +}
  345 +
  346 +.sec-bar {
  347 + width: 6rpx;
  348 + height: 28rpx;
  349 + background-color: #2563EB;
  350 + border-radius: 3rpx;
314 351 }
315 352  
316 353 .form-label {
317   - font-size: 28rpx;
318   - color: #303133;
319   - margin-bottom: 16rpx;
  354 + font-size: 30rpx;
  355 + font-weight: 500;
  356 + color: #1F2937;
  357 + margin-bottom: 0;
320 358 }
321 359  
  360 +// 处理人:整行选项,多个人之间用分隔线(设计稿 .row)
322 361 .worker-list {
323 362 display: flex;
324   - flex-wrap: wrap;
325   - gap: 16rpx;
  363 + flex-direction: column;
  364 + gap: 0;
  365 +
  366 + :deep(.u-radio) {
  367 + display: flex;
  368 + align-items: center;
  369 + padding: 20rpx 0;
  370 + margin-right: 0;
  371 + }
  372 +
  373 + :deep(.u-radio + .u-radio) {
  374 + border-top: 1rpx solid #E8EBF0;
  375 + }
  376 +
  377 + :deep(.u-radio__text) {
  378 + font-size: 28rpx;
  379 + color: #1F2937;
  380 + }
  381 +}
  382 +
  383 +// 文本域:浅灰底 + 圆角、去掉默认描边(设计稿 .textarea)
  384 +.unified-action-form :deep(.u-textarea) {
  385 + border: none;
  386 + background-color: #F4F6FA;
  387 + border-radius: 8rpx;
  388 +}
  389 +
  390 +.unified-action-form :deep(.u-textarea__field) {
  391 + font-size: 28rpx;
  392 + color: #1F2937;
  393 +}
  394 +
  395 +// 字数统计贴灰底显示(组件内部写死了白底,需 !important 覆盖)
  396 +.unified-action-form :deep(.u-textarea__count) {
  397 + background-color: transparent !important;
  398 + color: #9CA3AF;
326 399 }
327 400  
328 401 .unified-action-btns {
329 402 display: flex;
330 403 gap: 24rpx;
331   - margin-top: 20rpx;
  404 + margin-top: 32rpx;
332 405  
333 406 ::v-deep .u-button {
334 407 flex: 1;
  408 + height: 88rpx !important;
  409 + border-radius: 16rpx !important;
  410 + border: none !important;
  411 + }
  412 +
  413 + ::v-deep .u-button__text {
  414 + font-size: 32rpx !important;
  415 + font-weight: 500 !important;
  416 + }
  417 +
  418 + // 主按钮(确定):蓝色渐变
  419 + ::v-deep .u-button--primary {
  420 + background-image: linear-gradient(135deg, #1D4ED8 0%, #2563EB 60%, #3B82F6 100%) !important;
335 421 }
336 422 }
337 423 </style>
... ...
components/work-field-form/work-field-form.vue
... ... @@ -798,7 +798,7 @@ export default {
798 798 :deep(.u-number-box__input) {
799 799 width: 264rpx !important;
800 800 height: 72rpx;
801   - font-size: 32rpx;
  801 + font-size: 30rpx;
802 802 }
803 803  
804 804 :deep(.u-number-box__btn) {
... ... @@ -819,7 +819,7 @@ export default {
819 819  
820 820 .unit-text {
821 821 font-size: 28rpx;
822   - color: #333;
  822 + color: #1a1a1a;
823 823 }
824 824 }
825 825  
... ... @@ -853,7 +853,7 @@ export default {
853 853 flex: 1;
854 854 min-width: 0;
855 855 font-size: 28rpx;
856   - color: #333;
  856 + color: #1a1a1a;
857 857 }
858 858 }
859 859  
... ... @@ -878,14 +878,14 @@ export default {
878 878 flex: 1;
879 879 min-width: 0;
880 880 font-size: 28rpx;
881   - color: #333;
  881 + color: #1a1a1a;
882 882 overflow: hidden;
883 883 white-space: nowrap;
884 884 text-overflow: ellipsis;
885 885 }
886 886  
887 887 .file-del {
888   - font-size: 26rpx;
  888 + font-size: 28rpx;
889 889 color: #ff4d4f;
890 890 }
891 891 }
... ...
pages-sub/daily/attendanceRecord.vue
... ... @@ -254,17 +254,19 @@ onMounted(async () =&gt; {
254 254 </script>
255 255 <style scoped lang="scss">
256 256 .attendance-page {
257   - padding: 20rpx;
258   - background-color: #f5f5f7;
  257 + padding: 24rpx;
  258 + background-color: #F4F6FA;
259 259 min-height: 100vh;
  260 + box-sizing: border-box;
260 261 }
261 262  
262 263 .stat-card {
263 264 display: flex;
264   - background-color: #3c9cff;
  265 + background-color: #2563EB;
265 266 border-radius: 16rpx;
266 267 padding: 30rpx 0;
267   - margin-bottom: 20rpx;
  268 + margin-bottom: 24rpx;
  269 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
268 270  
269 271 .stat-item {
270 272 flex: 1;
... ... @@ -285,10 +287,11 @@ onMounted(async () =&gt; {
285 287 }
286 288  
287 289 .calendar-wrap {
288   - background: #fff;
289   - border-radius: 12rpx;
290   - padding: 20rpx;
291   - margin-bottom: 20rpx;
  290 + background-color: #ffffff;
  291 + border-radius: 16rpx;
  292 + padding: 24rpx;
  293 + margin-bottom: 24rpx;
  294 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
292 295 }
293 296  
294 297 .calendar-header {
... ... @@ -299,7 +302,7 @@ onMounted(async () =&gt; {
299 302 }
300 303  
301 304 .calendar-title {
302   - font-size: 32rpx;
  305 + font-size: 30rpx;
303 306 font-weight: bold;
304 307 }
305 308  
... ... @@ -307,7 +310,7 @@ onMounted(async () =&gt; {
307 310 padding: 8rpx 16rpx;
308 311 border: 1rpx solid #eee;
309 312 border-radius: 8rpx;
310   - font-size: 26rpx;
  313 + font-size: 28rpx;
311 314 }
312 315  
313 316 .empty-btn {
... ... @@ -321,8 +324,8 @@ onMounted(async () =&gt; {
321 324 .week-item {
322 325 flex: 1;
323 326 text-align: center;
324   - font-size: 26rpx;
325   - color: #666;
  327 + font-size: 28rpx;
  328 + color: #606266;
326 329 padding: 10rpx 0;
327 330 }
328 331 }
... ... @@ -363,13 +366,14 @@ onMounted(async () =&gt; {
363 366 }
364 367  
365 368 .detail-card {
366   - background: #fff;
367   - border-radius: 12rpx;
368   - padding: 30rpx;
  369 + background-color: #ffffff;
  370 + border-radius: 16rpx;
  371 + padding: 28rpx;
  372 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
369 373  
370 374 .empty-text {
371 375 text-align: center;
372   - color: #999;
  376 + color: #909399;
373 377 font-size: 30rpx;
374 378 padding: 40rpx 0;
375 379 }
... ... @@ -380,14 +384,14 @@ onMounted(async () =&gt; {
380 384  
381 385 .detail-title {
382 386 font-size: 30rpx;
383   - color: #333;
  387 + color: #1a1a1a;
384 388 width: 220rpx;
385 389 }
386 390  
387 391 .detail-text {
388 392 flex: 1;
389 393 font-size: 30rpx;
390   - color: #666;
  394 + color: #606266;
391 395 }
392 396 }
393 397  
... ...
pages-sub/daily/maintain-manage/add-record.vue
1 1 <template>
2 2 <view class="page-container">
3 3 <view class="inspect-form-content commonPageLRpadding" ref="formContentRef">
4   - <up-form label-position="left" :model="inspectForm" ref="inspectFormRef" label-width="140rpx">
  4 + <up-form label-position="left" :model="inspectForm" ref="inspectFormRef" label-width="180rpx">
  5 + <!-- 区块标题:蓝色竖条 + 标题(设计稿 .card) -->
  6 + <view v-if="dynamicFields.length > 0" class="sec-head">
  7 + <view class="sec-bar"></view>
  8 + <view class="sec-title">作业量填报</view>
  9 + </view>
5 10 <!-- ========== 动态表单区域 ========== -->
6 11 <template v-for="item in dynamicFields" :key="item.fieldCode">
7 12 <up-form-item :label="item.fieldName" :prop="item.fieldCode" class="form-item"
... ... @@ -129,6 +134,10 @@
129 134 <view v-if="dynamicFields.length === 0" class="empty-field-tip">
130 135 <text>请去平台配置业务类型字段</text>
131 136 </view>
  137 + <!-- 提交说明(设计稿底部注释文案) -->
  138 + <view class="submit-hint" v-if="dynamicFields.length > 0">
  139 + 【提交】仅记录本次作业,后续还可再次提交;【提交并结束本次任务】作业全部完成,无须再上报
  140 + </view>
132 141 <view class="fixed-bottom-btn-wrap" v-if="dynamicFields.length > 0">
133 142 <view class="btn-item btn-left" @click="submitInspect">
134 143 <text>提交</text>
... ... @@ -1077,14 +1086,78 @@ export default {
1077 1086 </script>
1078 1087  
1079 1088 <style lang="scss" scoped>
  1089 +// 页面:设计稿底 #F4F6FA,底部给固定操作栏留位(按钮 88rpx + 上下 24rpx)
1080 1090 .page-container {
1081   - padding-bottom: 120rpx;
  1091 + padding-bottom: calc(180rpx + constant(safe-area-inset-bottom));
  1092 + padding-bottom: calc(180rpx + env(safe-area-inset-bottom));
1082 1093 }
1083 1094  
  1095 +// 表单容器:不再整屏铺白,改为浮起的白卡(设计稿 .card)
1084 1096 .inspect-form-content {
1085   - background: #fff;
1086   - padding: 20rpx;
1087   - margin-bottom: 20rpx;
  1097 + background: transparent;
  1098 + padding: 24rpx;
  1099 + margin-bottom: 0;
  1100 +}
  1101 +
  1102 +// 表单卡:白底 / 8px 圆角 / 卡片阴影
  1103 +:deep(.u-form) {
  1104 + background-color: #ffffff;
  1105 + border-radius: 16rpx;
  1106 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  1107 + overflow: hidden;
  1108 +}
  1109 +
  1110 +// 区块标题:4rpx 蓝色竖条 + 30rpx 标题
  1111 +.sec-head {
  1112 + display: flex;
  1113 + align-items: center;
  1114 + gap: 12rpx;
  1115 + padding: 24rpx 24rpx 8rpx;
  1116 +}
  1117 +
  1118 +.sec-bar {
  1119 + flex-shrink: 0;
  1120 + width: 6rpx;
  1121 + height: 28rpx;
  1122 + background-color: #2563EB;
  1123 + border-radius: 3rpx;
  1124 +}
  1125 +
  1126 +.sec-title {
  1127 + font-size: 30rpx;
  1128 + font-weight: 500;
  1129 + color: #1F2937;
  1130 + line-height: 1.4;
  1131 +}
  1132 +
  1133 +// 表单行:标签 #1F2937 / 内容右对齐,行间 1rpx 分隔线(设计稿 .row)
  1134 +:deep(.u-form-item__body) {
  1135 + align-items: center !important;
  1136 + padding: 24rpx !important;
  1137 + border-bottom: 1rpx solid #E8EBF0;
  1138 +}
  1139 +
  1140 +:deep(.u-form-item:last-child .u-form-item__body) {
  1141 + border-bottom: none;
  1142 +}
  1143 +
  1144 +:deep(.u-form-item__body__left__content__label) {
  1145 + font-size: 28rpx;
  1146 + color: #1F2937;
  1147 +}
  1148 +
  1149 +// 输入框去掉 uview 默认方框,做成设计稿的「右对齐纯文本」
  1150 +:deep(.u-input) {
  1151 + padding: 0 !important;
  1152 + border: none !important;
  1153 + border-radius: 0 !important;
  1154 + background-color: transparent !important;
  1155 +}
  1156 +
  1157 +:deep(.u-input__content__field-wrapper__field) {
  1158 + text-align: right;
  1159 + font-size: 28rpx;
  1160 + color: #1F2937;
1088 1161 }
1089 1162  
1090 1163 .date-input-wrap {
... ... @@ -1096,7 +1169,7 @@ export default {
1096 1169 :deep(.u-number-box__input) {
1097 1170 width: 264rpx !important;
1098 1171 height: 72rpx;
1099   - font-size: 32rpx;
  1172 + font-size: 30rpx;
1100 1173 }
1101 1174  
1102 1175 :deep(.u-number-box__btn) {
... ... @@ -1117,7 +1190,7 @@ export default {
1117 1190  
1118 1191 .unit-text {
1119 1192 font-size: 28rpx;
1120   - color: #333;
  1193 + color: #1a1a1a;
1121 1194 }
1122 1195 }
1123 1196  
... ... @@ -1151,7 +1224,7 @@ export default {
1151 1224 flex: 1;
1152 1225 min-width: 0;
1153 1226 font-size: 28rpx;
1154   - color: #333;
  1227 + color: #1a1a1a;
1155 1228 }
1156 1229 }
1157 1230  
... ... @@ -1176,59 +1249,78 @@ export default {
1176 1249 flex: 1;
1177 1250 min-width: 0;
1178 1251 font-size: 28rpx;
1179   - color: #333;
  1252 + color: #1a1a1a;
1180 1253 overflow: hidden;
1181 1254 white-space: nowrap;
1182 1255 text-overflow: ellipsis;
1183 1256 }
1184 1257  
1185 1258 .file-del {
1186   - font-size: 26rpx;
  1259 + font-size: 28rpx;
1187 1260 color: #ff4d4f;
1188 1261 }
1189 1262 }
1190 1263 }
1191 1264  
  1265 +// 无字段配置提示:与表单卡同宽同圆角
1192 1266 .empty-field-tip {
1193   - padding: 80rpx 30rpx;
  1267 + margin: 0 24rpx;
  1268 + padding: 80rpx 24rpx;
1194 1269 text-align: center;
1195   - font-size: 30rpx;
1196   - color: #999;
  1270 + font-size: 26rpx;
  1271 + color: #9CA3AF;
  1272 + background-color: #ffffff;
  1273 + border-radius: 16rpx;
1197 1274 }
1198 1275  
  1276 +// 提交说明(设计稿底部注释文案)
  1277 +.submit-hint {
  1278 + padding: 24rpx;
  1279 + text-align: center;
  1280 + font-size: 22rpx;
  1281 + line-height: 1.6;
  1282 + color: #9CA3AF;
  1283 +}
  1284 +
  1285 +// 底部固定操作栏:白底 + 上分隔线;左「提交」白底描边,右「提交并结束」绿色主按钮
1199 1286 .fixed-bottom-btn-wrap {
1200   - background-color: #ffffff;
  1287 + position: fixed;
  1288 + left: 0;
  1289 + right: 0;
  1290 + bottom: 0;
  1291 + z-index: 10;
1201 1292 display: flex;
  1293 + gap: 24rpx;
  1294 + padding: 24rpx;
  1295 + padding-bottom: calc(24rpx + constant(safe-area-inset-bottom));
  1296 + padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
  1297 + background-color: #ffffff;
  1298 + border-top: 1rpx solid #E8EBF0;
  1299 + box-shadow: 0 -8rpx 28rpx rgba(17, 24, 39, 0.06);
  1300 +
1202 1301 .btn-item {
1203 1302 flex: 1;
1204 1303 height: 88rpx;
1205   -
1206 1304 display: flex;
1207 1305 align-items: center;
1208 1306 justify-content: center;
1209   - font-size: 32rpx;
1210   - color: #fff;
  1307 + font-size: 30rpx;
  1308 + border-radius: 16rpx;
  1309 + white-space: nowrap;
1211 1310 }
1212 1311  
1213 1312 .btn-left {
1214   - background: #1989fa;
  1313 + background-color: #ffffff;
  1314 + border: 1rpx solid #E8EBF0;
  1315 + color: #1F2937;
1215 1316 }
1216 1317  
1217 1318 .btn-right {
1218   - background: #8b572a;
1219   - /* 褐色 */
  1319 + /* 与顶部导航栏同色 */
  1320 + background-color: #2563EB;
  1321 + background-image: none;
  1322 + color: #ffffff;
  1323 + font-weight: 500;
1220 1324 }
1221 1325 }
1222   -
1223   -// 页面底部预留空白,防止表单内容被固定按钮遮挡
1224   -.page-container {
1225   - padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
1226   -}
1227   -
1228   -.empty-field-tip {
1229   - text-align: center;
1230   - padding: 80rpx 20rpx;
1231   - font-size: 30rpx;
1232   - color: #999;
1233   -}
1234 1326 </style>
... ...
pages-sub/daily/maintain-manage/finish-plan-detail.vue
... ... @@ -5,41 +5,40 @@
5 5 v-if="loading"
6 6 :loading="true"
7 7 title="加载中..."
8   - color="#3c9cff"
  8 + color="#2563EB"
9 9 ></up-loading-page>
10 10  
11 11 <!-- 内容容器 -->
12 12 <template v-else>
13 13 <view class="content-wrap" v-for="(i, index) in orderDetail" :key="index">
  14 + <!-- 1. 计划名称:独立标题卡(设计稿顶部白卡) -->
  15 + <view class="record-head">
  16 + <view class="record-title">{{i.planName || '--'}}</view>
  17 + </view>
14 18 <!-- 工单详情内容 -->
15   - <up-cell-group :border="false" inset>
16   - <!-- 1. 工单计划名称 -->
17   - <up-cell align="middle">
18   - <template #title>
19   - <view class="up-line-1">{{i.planName || '--'}}</view>
20   - </template>
21   - </up-cell>
  19 + <view class="form-card">
  20 + <!-- 区块标题:蓝色竖条 + 标题(设计稿 .card) -->
  21 + <view class="sec-head">
  22 + <view class="sec-bar"></view>
  23 + <view class="sec-title">作业信息</view>
  24 + </view>
22 25  
23 26 <!-- 2. 工单位置 -->
24   - <up-cell
25   - title="计划编码"
26   - :value="i.planNo || '--'"
27   - align="middle"
28   - ></up-cell>
  27 + <view class="u-body-item u-flex">
  28 + <view class="u-body-item-title">计划编码:</view>
  29 + <view class="u-line-1 u-body-value">{{ i.planNo || '--' }}</view>
  30 + </view>
29 31  
30   -
31   - <up-cell
32   - title="养护周期"
33   - :value="`${i.rate}${uni.$dict.getDictLabel('cycle_id_type', i.cycleId)}`"
34   - align="middle"
35   - ></up-cell>
  32 + <view class="u-body-item u-flex">
  33 + <view class="u-body-item-title">养护周期:</view>
  34 + <view class="u-line-1 u-body-value">{{ `${i.rate}${uni.$dict.getDictLabel('cycle_id_type', i.cycleId)}` }}</view>
  35 + </view>
36 36  
37 37 <!-- 4. 情况描述 -->
38   - <up-cell
39   - title="计划有效期"
40   - :value="`${timeFormat(i.beginTime,'yyyy-mm-dd')} 至 ${timeFormat(i.endTime,'yyyy-mm-dd')}`"
41   - align="middle"
42   - ></up-cell>
  38 + <view class="u-body-item u-flex">
  39 + <view class="u-body-item-title">计划有效期:</view>
  40 + <view class="u-line-1 u-body-value">{{ `${timeFormat(i.beginTime,'yyyy-mm-dd')} 至 ${timeFormat(i.endTime,'yyyy-mm-dd')}` }}</view>
  41 + </view>
43 42  
44 43 <!-- 5. 问题照片(核心修复:兼容WebP + 强制尺寸) -->
45 44 <!-- <up-cell title="照片">
... ... @@ -87,38 +86,31 @@
87 86  
88 87  
89 88  
90   - <up-cell
91   - title="提交人"
92   - :value="i.userName || '--'"
93   - align="middle"
94   -
95   - ></up-cell>
  89 + <view class="u-body-item u-flex">
  90 + <view class="u-body-item-title">提交人:</view>
  91 + <view class="u-line-1 u-body-value">{{ i.userName || '--' }}</view>
  92 + </view>
96 93  
97   - <up-cell
98   - title="提交时间"
99   - :value="i.createTime==null?'--':timeFormat(i.createTime,'yyyy-mm-dd hh:MM:ss')"
100   - align="middle"
101   - ></up-cell>
102   - </up-cell-group>
  94 + <view class="u-body-item u-flex">
  95 + <view class="u-body-item-title">提交时间:</view>
  96 + <view class="u-line-1 u-body-value">{{ i.createTime==null?'--':timeFormat(i.createTime,'yyyy-mm-dd hh:MM:ss') }}</view>
  97 + </view>
  98 + </view>
103 99  
104 100 <!-- 动态配置的养护字段填报值(garden_work_record/garden_work_field_value),未填报过则整段不显示 -->
105 101 <!-- 动态配置的养护字段填报值(garden_work_record/garden_work_field_value),未填报过则整段不显示 -->
106   -<up-cell-group
  102 +<view
  103 + class="form-card"
107 104 v-if="i.fieldRows && i.fieldRows.length"
108   - :border="false"
109   - inset
110   - title=""
111 105 >
112   - <up-cell v-for="(f, fi) in i.fieldRows" :key="fi" align="middle">
113   - <!-- <up-cell
114   - title="提交时间"
115   - :value="i.createTime==null?'--':timeFormat(i.createTime,'yyyy-mm-dd hh:MM:ss')"
116   - align="middle"
117   - ></up-cell> -->
118   - <template #title>
119   -<view class="field-cell-title-multi">{{f.name}}</view>
120   - </template>
121   - <template #value>
  106 + <!-- 区块标题:蓝色竖条 + 标题 -->
  107 + <view class="sec-head">
  108 + <view class="sec-bar"></view>
  109 + <view class="sec-title">养护填报内容</view>
  110 + </view>
  111 + <view class="u-body-item u-flex field-row" v-for="(f, fi) in i.fieldRows" :key="fi">
  112 + <view class="u-body-item-title field-cell-title-multi">{{ f.name }}</view>
  113 + <view class="field-value">
122 114 <!-- 7 图片:复用本页照片的相册组件(预览/尺寸一致) -->
123 115 <up-album
124 116 v-if="f.kind === 'image'"
... ... @@ -146,9 +138,9 @@
146 138 <text v-else-if="f.kind === 'geo' && f.geo" class="field-link" @click="openGeo(f.geo)">{{ f.text }}</text>
147 139 <!-- 其余(1数值/2文本/3单选枚举/4日期/5布尔等)文本直出 -->
148 140 <text v-else class="common-text-color field-text">{{ f.text }}</text>
149   - </template>
150   - </up-cell>
151   -</up-cell-group>
  141 + </view>
  142 + </view>
  143 +</view>
152 144 <!-- 当没有填报字段,提示暂无提交记录 -->
153 145 <view v-else class="no-record-tip">
154 146 直接结束了本次任务
... ... @@ -552,12 +544,85 @@ onLoad((options) =&gt; {
552 544 </script>
553 545  
554 546 <style scoped lang="scss">
555   -// 内容容器
  547 +// 页面底色(设计稿 #F4F6FA)
  548 +.page-container {
  549 + min-height: 100vh;
  550 + background-color: #F4F6FA;
  551 + box-sizing: border-box;
  552 +}
  553 +
  554 +// 内容容器:卡片自带圆角与外边距,容器不再铺白底(设计稿页面底 #F4F6FA)
556 555 .content-wrap {
557   - background: #fff;
  556 + background: transparent;
558 557 width: 100%;
559 558 box-sizing: border-box;
560   - margin-bottom: 30rpx;
  559 + padding-top: 24rpx;
  560 + margin-bottom: 8rpx;
  561 +}
  562 +
  563 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  564 +.form-card {
  565 + margin: 0 24rpx 24rpx;
  566 + padding: 8rpx 24rpx 24rpx;
  567 + background-color: #ffffff;
  568 + border-radius: 16rpx;
  569 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  570 +}
  571 +.form-card .u-body-item {
  572 + margin-bottom: 12rpx;
  573 +}
  574 +.field-row:last-child {
  575 + margin-bottom: 0;
  576 +}
  577 +.field-value {
  578 + flex: 1;
  579 + min-width: 0;
  580 +}
  581 +
  582 +// 计划名称标题卡:白底 / 8px 圆角 / 卡片阴影 / 32rpx 500(设计稿顶部卡)
  583 +.record-head {
  584 + display: flex;
  585 + align-items: center;
  586 + margin: 0 24rpx 24rpx;
  587 + padding: 24rpx;
  588 + background: #ffffff;
  589 + border-radius: 16rpx;
  590 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  591 +}
  592 +
  593 +.record-title {
  594 + flex: 1;
  595 + min-width: 0;
  596 + font-size: 32rpx;
  597 + font-weight: 500;
  598 + color: #1F2937;
  599 + line-height: 1.4;
  600 + overflow: hidden;
  601 + white-space: nowrap;
  602 + text-overflow: ellipsis;
  603 +}
  604 +
  605 +// 区块标题:4rpx 蓝色竖条 + 30rpx 标题(设计稿 .card 标题)
  606 +.sec-head {
  607 + display: flex;
  608 + align-items: center;
  609 + gap: 12rpx;
  610 + padding: 20rpx 0 8rpx;
  611 +}
  612 +
  613 +.sec-bar {
  614 + flex-shrink: 0;
  615 + width: 6rpx;
  616 + height: 28rpx;
  617 + background-color: #2563EB;
  618 + border-radius: 3rpx;
  619 +}
  620 +
  621 +.sec-title {
  622 + font-size: 30rpx;
  623 + font-weight: 500;
  624 + color: #1F2937;
  625 + line-height: 1.4;
561 626 }
562 627  
563 628 // 图片容器样式
... ... @@ -589,7 +654,7 @@ onLoad((options) =&gt; {
589 654  
590 655 // 空文本样式
591 656 .empty-text {
592   - color: #999;
  657 + color: #909399;
593 658 font-size: 14px;
594 659 line-height: 70px; // 和图片高度对齐
595 660 }
... ... @@ -605,17 +670,17 @@ onLoad((options) =&gt; {
605 670  
606 671 // 自绘标签:仓库未使用过 up-tag,避免引入未验证组件
607 672 .field-tag {
608   - padding: 2rpx 12rpx;
609   - background: #f2f3f5;
610   - border-radius: 6rpx;
611   - color: #606266;
612   - font-size: 24rpx;
613   - line-height: 36rpx;
  673 + padding: 0 16rpx;
  674 + background: #F4F6FA;
  675 + border-radius: 8rpx;
  676 + color: #4B5563;
  677 + font-size: 22rpx;
  678 + line-height: 40rpx;
614 679 }
615 680  
616 681 // 附件(可点击打开)
617 682 .field-file {
618   - color: #3c9cff;
  683 + color: #2563EB;
619 684 font-size: 26rpx;
620 685 margin-left: 16rpx;
621 686 text-decoration: underline;
... ... @@ -623,7 +688,7 @@ onLoad((options) =&gt; {
623 688  
624 689 // 链接 / 地理位置(可点击)
625 690 .field-link {
626   - color: #3c9cff;
  691 + color: #2563EB;
627 692 font-size: 26rpx;
628 693 word-break: break-all;
629 694 }
... ... @@ -637,10 +702,15 @@ onLoad((options) =&gt; {
637 702 min-width: 160rpx; // 固定左侧标题最大宽度,文字会在这个宽度内自动换行
638 703 }
639 704  
  705 +// 无填报记录提示:与上方信息卡同宽同圆角
640 706 .no-record-tip {
641   - padding:24rpx 30rpx;
642   - font-size:26rpx;
643   - color:#999;
  707 + margin: 0 24rpx 24rpx;
  708 + padding: 24rpx;
  709 + background: #ffffff;
  710 + border-radius: 16rpx;
  711 + font-size: 26rpx;
  712 + color: #9CA3AF;
  713 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
644 714 }
645 715  
646 716  
... ...
pages-sub/daily/maintain-manage/index.vue
... ... @@ -8,8 +8,8 @@
8 8 v-model="activeType"
9 9 :list="typeTabs"
10 10 line-width="40rpx"
11   - active-color="#1989fa"
12   - inactive-color="#666"
  11 + active-color="#2563EB"
  12 + inactive-color="#606266"
13 13 :scrollable="true"
14 14 class="first-tabs"
15 15 @click="handleTypeChange"
... ... @@ -20,8 +20,8 @@
20 20 v-model="activeStatus"
21 21 :list="statusTabs"
22 22 line-width="40rpx"
23   - active-color="#1989fa"
24   - inactive-color="#666"
  23 + active-color="#2563EB"
  24 + inactive-color="#606266"
25 25 :scrollable="true"
26 26 class="second-tabs"
27 27 @click="handleStatusChange"
... ... @@ -40,7 +40,7 @@
40 40 @custom="handleSearch"
41 41 :clearabled="false"
42 42 maxlength="50"
43   - style="margin: 0rpx 20rpx 0"
  43 + style="margin: 0rpx 24rpx 0"
44 44 ></up-search>
45 45 </view>
46 46 </up-sticky>
... ... @@ -58,32 +58,28 @@
58 58 </template>
59 59  
60 60 <!-- 道路类型卡片 -->
61   - <view v-if="activeType === '道路'" class="common-card-list" style="padding-top: 34px;">
  61 + <view v-if="activeType === '道路'" class="common-card-list maintain-card-list">
62 62  
63 63 <up-card
64 64 :border="false"
65 65 :foot-border-top="false"
66 66 :head-border-bottom="false"
  67 + margin="0"
  68 + padding-head="24rpx 24rpx 0"
  69 + padding-body="16rpx 24rpx 24rpx"
  70 + box-shadow="0 4rpx 16rpx rgba(17, 24, 39, 0.06)"
67 71 v-for="(item,index) in currentList"
68 72 :key="`${item.planNo}_${index}`"
69   - :show-head="false"
70 73 >
  74 + <!-- 卡片标题:道路名称 -->
  75 + <template #head>
  76 + <view class="card-header">
  77 + <view class="common-card-title common-name u-line-1">{{ item.roadName || '无道路名称' }}</view>
  78 + </view>
  79 + </template>
  80 +
71 81 <template #body>
72 82 <view class="card-body">
73   -<!-- <view class="">-->
74   -<!-- <up-button-->
75   -<!-- type="primary"-->
76   -<!-- size="mini"-->
77   -<!-- @click="goToDetail(item)"-->
78   -<!-- class="submit-record-btn"-->
79   -<!-- >-->
80   -<!-- 计划明细-->
81   -<!-- </up-button>-->
82   -<!-- </view>-->
83   -
84   - <view class="common-custom-btn" style="--btn-top: 48px;" @click="goToDetail(item)">
85   - 养护任务
86   - </view>
87 83 <!-- <view class="u-body-item u-flex">-->
88 84 <!-- <view class="u-body-item-title">批次号:</view>-->
89 85 <!-- <view class="u-line-1 u-body-value">{{ item.batchNo || '-' }}</view>-->
... ... @@ -105,14 +101,18 @@
105 101 </view> -->
106 102  
107 103 <view class="u-body-item u-flex">
108   - <view class="u-body-item-title">业务线:</view>
109   - <view class="u-line-1 u-body-value">{{ uni.$dict.getDictLabel('business_line', item.busiLine) || item.busiLine || '-' }}</view>
110   -</view>
111   -
  104 + <view class="u-body-item-title">业务线:</view>
  105 + <view class="u-line-1 u-body-value">{{ uni.$dict.getDictLabel('business_line', item.busiLine) || item.busiLine || '-' }}</view>
  106 + </view>
112 107  
113   - <view class="u-body-item u-flex common-item-center common-justify-between">
114   - <view class="u-body-item-title">养护级别: {{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}</view>
  108 + <view class="u-body-item u-flex">
  109 + <view class="u-body-item-title">养护级别:</view>
  110 + <view class="u-line-1 u-body-value">{{ uni.$dict.getDictLabel('conserve_level', item.levelId) || '-' }}</view>
  111 + </view>
115 112  
  113 + <!-- 操作区:统一收底 -->
  114 + <view class="card-action-row">
  115 + <view class="mini-btn mini-btn--primary" @click="goToDetail(item)">执行任务</view>
116 116 </view>
117 117  
118 118 <!-- <view class="u-body-item u-flex">-->
... ... @@ -127,11 +127,16 @@
127 127 </view>
128 128  
129 129 <!-- 其他养护类型卡片(补植/浇水等) -->
130   - <view v-else class="common-card-list" style="padding-top: 144px;">
  130 + <view v-else class="common-card-list maintain-card-list">
131 131  
132 132 <up-card
133 133 :border="false"
134 134 :foot-border-top="false"
  135 + :head-border-bottom="false"
  136 + margin="0"
  137 + padding-head="24rpx 24rpx 0"
  138 + padding-body="16rpx 24rpx 24rpx"
  139 + box-shadow="0 4rpx 16rpx rgba(17, 24, 39, 0.06)"
135 140 v-for="(item,index) in currentList"
136 141 :key="`${item.planNo}_${index}`"
137 142  
... ... @@ -145,9 +150,6 @@
145 150  
146 151 <template #body>
147 152 <view class="card-body">
148   - <view class="common-custom-btn " v-if="item.finishState!==3" style="--btn-top: 100px;" @click="submitRecord(item)">
149   - 提交记录
150   - </view>
151 153 <view class="u-body-item u-flex">
152 154 <view class="u-body-item-title">计划编码:</view>
153 155 <view class="u-line-1 u-body-value">{{ item.planNo || '-' }}</view>
... ... @@ -159,18 +161,9 @@
159 161 </view>
160 162 </view>
161 163  
162   - <view class="u-body-item u-flex common-item-center common-justify-between">
163   - <view class="u-body-item-title">计划完成次数: {{ item.planNum || 0 }}</view>
164   -<!-- <view class="" v-if="item.finishState!==3">-->
165   -<!-- <up-button-->
166   -<!-- type="primary"-->
167   -<!-- size="mini"-->
168   -<!-- @click="submitRecord(item)"-->
169   -<!-- class="submit-record-btn"-->
170   -<!-- >-->
171   -<!-- 提交记录-->
172   -<!-- </up-button>-->
173   -<!-- </view>-->
  164 + <view class="u-body-item u-flex">
  165 + <view class="u-body-item-title">计划完成次数:</view>
  166 + <view class="u-line-1 u-body-value">{{ item.planNum || 0 }}</view>
174 167 </view>
175 168  
176 169 <view class="u-body-item u-flex">
... ... @@ -184,6 +177,11 @@
184 177 {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }}
185 178 </view>
186 179 </view>
  180 +
  181 + <!-- 操作区:统一收底 -->
  182 + <view class="card-action-row" v-if="item.finishState!==3">
  183 + <view class="mini-btn mini-btn--primary" @click="submitRecord(item)">提交记录</view>
  184 + </view>
187 185 </view>
188 186 </template>
189 187 </up-card>
... ... @@ -343,16 +341,40 @@ onShow(()=&gt;{
343 341 </script>
344 342  
345 343 <style scoped lang="scss">
  344 +
  345 +/* 页面底色:统一浅灰蓝(设计稿 --page-bg) */
  346 +.page-container {
  347 + min-height: 100vh;
  348 + background-color: #F4F6FA;
  349 + box-sizing: border-box;
  350 +}
346 351 // 吸顶区域样式
  352 +/* 筛选条:上下各 12px(设计稿 .search-bar 上 8px / 下 12px,
  353 + * 本页类型 Tabs 在代码里是注释状态,没有 Tabs 时上下取同一档 12px 更匀) */
347 354 .sticky-wrap {
348 355 background-color: #fff;
349   - padding-bottom: 10rpx;
350   - border-bottom: 1px solid #eee;
  356 + padding: 24rpx 0;
  357 + border-bottom: 1rpx solid #E8EBF0;
351 358  
352 359 .first-tabs, .second-tabs {
353 360 margin: 10rpx 0;
354 361 }
355 362 }
356 363  
  364 +/* 卡片列表:页面左右 24rpx、卡片之间 24rpx(设计稿 .body)
  365 + * 顶部留白 = 吸顶筛选条高度(12+32+12=56px) + 12px 间距;z-paging 内容从容器顶部起算,
  366 + * 不留这段会被吸顶筛选条盖住卡片标题 */
  367 +.maintain-card-list {
  368 + display: flex;
  369 + flex-direction: column;
  370 + gap: 24rpx;
  371 + padding: 136rpx 24rpx 24rpx;
  372 +}
  373 +
  374 +/* 卡片体:内边距由 up-card 的 paddingBody 控制,此处不再叠加 */
  375 +.card-body {
  376 + padding: 0;
  377 +}
  378 +
357 379  
358 380 </style>
359 381 \ No newline at end of file
... ...
pages-sub/daily/maintain-manage/now-list-page.vue
... ... @@ -111,32 +111,64 @@ const handleAddReport = () =&gt; {
111 111 <style scoped lang="scss">
112 112 .page-wrap {
113 113 min-height: 100vh;
114   - padding-bottom: 120rpx; // 给底部按钮预留空间
115   - background: #ffffff;
  114 + // 底部固定栏(按钮 88rpx + 上下各 24rpx)+ 安全区
  115 + padding-bottom: calc(180rpx + constant(safe-area-inset-bottom));
  116 + padding-bottom: calc(180rpx + env(safe-area-inset-bottom));
  117 + background: #F4F6FA;
116 118 }
117   -// 顶部黄色提示条
  119 +// 顶部提示条:浅蓝底 + 蓝字 + 圆形感叹号(设计稿 .banner)
118 120 .tip-bar {
119   - background-color: #f9e0a2;
120   - color: #6b4b00;
121   - font-size: 28rpx;
122   - padding: 24rpx 20rpx;
123   - line-height: 1.5;
  121 + display: flex;
  122 + align-items: flex-start;
  123 + gap: 12rpx;
  124 + margin: 24rpx 24rpx 0;
  125 + padding: 16rpx 24rpx;
  126 + background-color: #EBF3FF;
  127 + border-radius: 16rpx;
  128 + color: #2563EB;
  129 + font-size: 24rpx;
  130 + line-height: 1.6;
  131 +
  132 + &::before {
  133 + content: "!";
  134 + box-sizing: border-box;
  135 + flex: 0 0 auto;
  136 + width: 30rpx;
  137 + height: 30rpx;
  138 + margin-top: 4rpx;
  139 + line-height: 26rpx;
  140 + text-align: center;
  141 + font-size: 22rpx;
  142 + font-weight: 600;
  143 + color: #2563EB;
  144 + border: 2rpx solid #2563EB;
  145 + border-radius: 50%;
  146 + }
124 147 }
  148 +// 记录卡片列表:卡片之间 24rpx(设计稿 .body)
125 149 .list-wrap {
126   - padding: 0;
  150 + display: flex;
  151 + flex-direction: column;
  152 + gap: 24rpx;
  153 + padding: 24rpx;
127 154 }
  155 +// 卡片:白底 / 8px 圆角 / 卡片阴影(设计稿 .card)
128 156 .report-item {
129   - padding: 30rpx 24rpx;
130   - border-bottom: 1rpx solid #eee;
  157 + padding: 24rpx;
  158 + background-color: #ffffff;
  159 + border-radius: 16rpx;
  160 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  161 +
131 162 .item-title {
132 163 font-size: 32rpx;
133   - color: #222;
  164 + color: #1F2937;
134 165 font-weight: 500;
135   - margin-bottom: 20rpx;
  166 + line-height: 1.4;
  167 + margin-bottom: 16rpx;
136 168 }
137 169 .item-row {
138   - font-size: 28rpx;
139   - color: #555;
  170 + font-size: 26rpx;
  171 + color: #4B5563;
140 172 margin-bottom: 12rpx;
141 173 }
142 174 .item-row-bottom {
... ... @@ -145,20 +177,50 @@ const handleAddReport = () =&gt; {
145 177 align-items: center;
146 178 margin-bottom: 0;
147 179 }
  180 + // 查看:次要操作,白底描边(设计稿 .btn 次级按钮)
148 181 .look-btn {
149   - font-size: 28rpx;
150   - color: #1989fa;
  182 + box-sizing: border-box;
  183 + display: flex;
  184 + align-items: center;
  185 + justify-content: center;
  186 + min-width: 120rpx;
  187 + height: 56rpx;
  188 + padding: 0 24rpx;
  189 + font-size: 24rpx;
  190 + color: #4B5563;
  191 + background-color: #ffffff;
  192 + border: 1rpx solid #E8EBF0;
  193 + border-radius: 8rpx;
  194 + flex-shrink: 0;
151 195 }
152 196 }
153 197 .empty-wrap {
154 198 padding-top: 120rpx;
155 199 }
  200 +// 底部固定操作栏:白底 + 上分隔线 + 蓝色渐变主按钮(设计稿 .bar / .btn.pri)
156 201 .fixed-bottom-btn-wrap {
157   - // position: fixed;
158   - // bottom: 0;
159   - // left:0;
160   - // width:100%;
161   - // padding:20rpx;
162   - // background:#fff;
  202 + position: fixed;
  203 + left: 0;
  204 + right: 0;
  205 + bottom: 0;
  206 + z-index: 10;
  207 + padding: 24rpx 24rpx calc(24rpx + constant(safe-area-inset-bottom));
  208 + padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
  209 + background-color: #ffffff;
  210 + border-top: 1rpx solid #E8EBF0;
  211 +
  212 + :deep(.u-button) {
  213 + height: 88rpx !important;
  214 + border-radius: 16rpx !important;
  215 + border: none !important;
  216 + /* 与顶部导航栏同色 */
  217 + background-color: #2563EB !important;
  218 + background-image: none !important;
  219 + }
  220 +
  221 + :deep(.u-button__text) {
  222 + font-size: 30rpx !important;
  223 + font-weight: 500 !important;
  224 + }
163 225 }
164 226 </style>
... ...
pages-sub/daily/maintain-manage/pending-plan-detail.vue
1 1 <template>
2 2 <view class="page-container">
3   - <!-- 计划详情卡片区域(复用目标卡片结构) -->
4   - <view class="common-card-list">
5   - <up-card
6   - :border="false"
7   - :foot-border-top="false"
8   - v-for="(i, index) in planInfo"
9   - :key="`${i.planNo}_${index}`"
10   - >
11   - <!-- 自定义标题区域(计划名称) -->
12   - <template #head>
13   - <view class="card-header">
14   - <view class="common-card-title u-line-1">{{ i.planName || '无计划名称' }}</view>
  3 + <!-- 计划详情卡片区域(统一卡片样式) -->
  4 + <view class="page-body">
  5 + <view class="plan-card-wrap" v-for="(i, index) in planInfo" :key="`${i.planNo}_${index}`">
  6 +
  7 + <!-- 计划名称 -->
  8 + <view class="form-card form-card--title">
  9 + <view class="card-title">{{ i.planName || '无计划名称' }}</view>
  10 + </view>
  11 +
  12 + <!-- 计划信息 -->
  13 + <view class="form-card">
  14 + <view class="sec-head">
  15 + <view class="sec-bar"></view>
  16 + <view class="sec-title">计划信息</view>
15 17 </view>
16   - </template>
17   -
18   - <!-- 卡片主体内容(原详情项) -->
19   - <template #body>
20   - <view class="card-body">
21   -<!-- <view class="">-->
22   -<!-- <up-button-->
23   -<!-- type="primary"-->
24   -<!-- size="mini"-->
25   -<!-- @click="gotoFinishPlanDetail(i)"-->
26   -<!-- class="submit-record-btn"-->
27   -
28   -<!-- >-->
29   -<!-- 查看记录-->
30   -<!-- </up-button>-->
31   -<!-- </view>-->
32   - <view class="common-custom-btn " style="--btn-top: 100px;" @click="gotoFinishPlanDetail(i)">
33   - 查看记录
34   - </view>
  18 +
35 19 <!-- 计划编码 -->
36 20 <view class="u-body-item u-flex">
37 21 <view class="u-body-item-title">计划编码:</view>
... ... @@ -66,22 +50,25 @@
66 50 {{ timeFormat(i.endTime, 'yyyy-mm-dd') || '-' }}
67 51 </view>
68 52 </view>
  53 +
  54 + <!-- 底部操作区(分隔线 + 右对齐按钮) -->
  55 + <view class="card-action-row">
  56 + <view class="mini-btn mini-btn--primary" @click="gotoFinishPlanDetail(i)">查看记录</view>
69 57 </view>
70   - </template>
71   - </up-card>
72   -
73   - <!-- 底部新增记录按钮 -->
74   - <view class="fixed-bottom-btn-wrap" v-if="finishState==1">
75   - <up-button
76   - type="primary"
77   - size="default"
78   - @click="addNewRecord"
79   - :style="{ width: '100%', height: '88rpx', fontSize: '32rpx', borderRadius: 0 }"
80   - >
81   - 新增记录
82   - </up-button>
  58 + </view>
83 59 </view>
84 60 </view>
  61 +
  62 + <!-- 底部新增记录按钮 -->
  63 + <view class="fixed-bottom-btn-wrap" v-if="finishState==1">
  64 + <up-button
  65 + type="primary"
  66 + size="default"
  67 + @click="addNewRecord"
  68 + >
  69 + 新增记录
  70 + </up-button>
  71 + </view>
85 72 </view>
86 73 </template>
87 74  
... ... @@ -149,7 +136,63 @@ const addNewRecord = () =&gt; {
149 136 </script>
150 137  
151 138 <style scoped lang="scss">
  139 +/* 统一卡片样式(与巡查计划明细一致) */
152 140 .page-container {
  141 + min-height: 100vh;
  142 + padding-bottom: 200rpx;
  143 + background-color: #F4F6FA;
  144 + box-sizing: border-box;
  145 +}
  146 +
  147 +.page-body {
  148 + padding: 0 24rpx;
  149 +}
153 150  
  151 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  152 +.form-card {
  153 + margin-top: 24rpx;
  154 + padding: 8rpx 24rpx 24rpx;
  155 + background-color: #ffffff;
  156 + border-radius: 16rpx;
  157 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  158 +}
  159 +
  160 +// 区块标题:蓝色竖条 + 标题文字
  161 +.sec-head {
  162 + display: flex;
  163 + align-items: center;
  164 + gap: 12rpx;
  165 + padding: 20rpx 0 8rpx;
  166 +}
  167 +.sec-bar {
  168 + width: 6rpx;
  169 + height: 28rpx;
  170 + background-color: #2563EB;
  171 + border-radius: 3rpx;
  172 +}
  173 +.sec-title {
  174 + font-size: 30rpx;
  175 + font-weight: 500;
  176 + color: #1F2937;
  177 +}
  178 +
  179 +/* 计划名称卡片 */
  180 +.form-card--title {
  181 + padding: 28rpx 24rpx;
  182 +}
  183 +.card-title {
  184 + font-size: 32rpx;
  185 + font-weight: 500;
  186 + color: #1F2937;
  187 + line-height: 1.4;
  188 +}
  189 +
  190 +/* 信息行 */
  191 +.form-card .u-body-item {
  192 + margin-bottom: 12rpx;
  193 +
  194 + &:last-of-type {
  195 + margin-bottom: 0;
  196 + }
154 197 }
155 198 </style>
156 199 \ No newline at end of file
... ...
pages-sub/daily/maintain-manage/record-detail-list.vue
... ... @@ -5,93 +5,63 @@
5 5 v-if="loading"
6 6 :loading="true"
7 7 title="加载中..."
8   - color="#3c9cff"
  8 + color="#2563EB"
9 9 ></up-loading-page>
10 10  
11 11 <!-- 内容容器 -->
12 12 <view v-else class="content-wrap">
13 13  
14 14  
15   - <template v-for="(i, index) in orderDetail" :key="index">
16   - <!-- 工单详情内容 -->
17   - <up-cell-group :border="false" inset style="margin: 20rpx;">
18   - <!-- 1. 工单编号 -->
19   - <up-cell
20   - :title="i.planName"
21   -
22   - class="up-line-1"
23   - align="middle"
24   - ></up-cell>
25   -
26   - <!-- 2. 工单位置 -->
27   - <up-cell
28   - title="计划编码"
29   - :value="i.planNo || '--'"
30   - class="up-line-1"
31   - align="middle"
32   - ></up-cell>
33   -
34   -
35   - <up-cell
36   - title="养护周期"
37   - :value="`${i.rate}${uni.$dict.getDictLabel('cycle_id_type', i.cycleId)}`"
38   - class="up-line-1"
39   - align="middle"
40   - ></up-cell>
41   -
42   - <!-- 4. 情况描述 -->
43   - <up-cell
44   - title="计划有效期"
45   - :value="`${timeFormat(i.beginTime,'yy-mm-dd hh:MM:ss')} 至 ${timeFormat(i. endTime,'yy-mm-dd hh:MM:ss')}`"
46   - class="up-line-1"
47   - align="middle"
48   - ></up-cell>
49   -
50   - <!-- 5. 问题照片(核心修复:判断条件+空值处理) -->
51   - <up-cell title="照片" >
52   - <template #value>
53   - <view class="cell-content-wrap">
54   -
55   - <!-- 修复1:正确判断problemImgsList,补充空数组默认值 -->
56   - <up-album
57   - v-if="!!i.imgList?.length"
58   - :urls="i.imgList || []"
59   - singleSize="70"
60   - :preview-full-image="true"
61   -
62   - ></up-album>
63   - <text v-else class="empty-text">暂无问题照片</text>
64   - </view>
65   - </template>
66   - </up-cell>
67   -
68   - <!-- 7. 处理结果 -->
69   - <up-cell
70   - title="养护描述"
71   - :value="i.remark || '--'"
72   - class="up-line-1"
73   - align="middle"
74   - :border="false"
75   - ></up-cell>
76   -
77   - <up-cell
78   - title="提交时间"
79   - :value="timeFormat(i.finishTime,'yy-mm-dd hh:MM:ss') || '--'"
80   - class="up-line-1"
81   - align="middle"
82   - :border="false"
83   - ></up-cell>
84   -
85   -
86   - <up-cell
87   - title="提交人"
88   - :value="i.userName || '--'"
89   - class="up-line-1"
90   - align="middle"
91   - :border="false"
92   - ></up-cell>
93   - </up-cell-group>
94   - </template>
  15 + <!-- 养护记录卡片(统一卡片样式) -->
  16 + <view class="plan-card" v-for="(i, index) in orderDetail" :key="index">
  17 + <view class="plan-card__head">
  18 + <view class="plan-card__title">{{ i.planName || '无计划名称' }}</view>
  19 + </view>
  20 +
  21 + <view class="u-body-item u-flex">
  22 + <view class="u-body-item-title">计划编码:</view>
  23 + <view class="u-line-1 u-body-value">{{ i.planNo || '--' }}</view>
  24 + </view>
  25 +
  26 + <view class="u-body-item u-flex">
  27 + <view class="u-body-item-title">养护周期:</view>
  28 + <view class="u-line-1 u-body-value">{{ `${i.rate}${uni.$dict.getDictLabel('cycle_id_type', i.cycleId)}` }}</view>
  29 + </view>
  30 +
  31 + <view class="u-body-item u-flex">
  32 + <view class="u-body-item-title">计划有效期:</view>
  33 + <view class="u-line-1 u-body-value">{{ `${timeFormat(i.beginTime,'yy-mm-dd hh:MM:ss')} 至 ${timeFormat(i. endTime,'yy-mm-dd hh:MM:ss')}` }}</view>
  34 + </view>
  35 +
  36 + <view class="u-body-item u-flex">
  37 + <view class="u-body-item-title">养护描述:</view>
  38 + <view class="u-line-1 u-body-value">{{ i.remark || '--' }}</view>
  39 + </view>
  40 +
  41 + <view class="u-body-item u-flex">
  42 + <view class="u-body-item-title">提交时间:</view>
  43 + <view class="u-line-1 u-body-value">{{ timeFormat(i.finishTime,'yy-mm-dd hh:MM:ss') || '--' }}</view>
  44 + </view>
  45 +
  46 + <view class="u-body-item u-flex">
  47 + <view class="u-body-item-title">提交人:</view>
  48 + <view class="u-line-1 u-body-value">{{ i.userName || '--' }}</view>
  49 + </view>
  50 +
  51 + <!-- 照片 -->
  52 + <view class="photo-block">
  53 + <view class="u-body-item-title">照片:</view>
  54 + <view class="cell-content-wrap">
  55 + <up-album
  56 + v-if="!!i.imgList?.length"
  57 + :urls="i.imgList || []"
  58 + singleSize="70"
  59 + :preview-full-image="true"
  60 + ></up-album>
  61 + <text v-else class="empty-text">暂无问题照片</text>
  62 + </view>
  63 + </view>
  64 + </view>
95 65  
96 66  
97 67 </view>
... ... @@ -144,48 +114,66 @@ onLoad((options) =&gt; {
144 114  
145 115 <style scoped lang="scss">
146 116 // 页面基础样式
  117 +.page-container,
147 118 .u-page {
148 119 min-height: 100vh;
149   - background-color: #f5f5f5;
  120 + padding-bottom: 40rpx;
  121 + background-color: #F4F6FA;
150 122 box-sizing: border-box;
151 123 }
152 124  
153 125 // 内容容器
154 126 .content-wrap {
155   - background: #fff;
  127 + padding: 0 24rpx;
156 128 width: 100%;
157 129 box-sizing: border-box;
158 130 overflow-y: auto;
159   - min-height: calc(100vh - 40rpx);
160 131 }
161 132  
  133 +/* 养护记录卡片:白底圆角 + 标题 + 底部操作区 */
  134 +.plan-card {
  135 + margin: 24rpx 0 0;
  136 + padding: 28rpx 28rpx 24rpx;
  137 + background-color: #ffffff;
  138 + border-radius: 16rpx;
  139 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  140 +}
  141 +.plan-card__head {
  142 + display: flex;
  143 + align-items: center;
  144 + justify-content: space-between;
  145 + margin-bottom: 20rpx;
  146 +}
  147 +.plan-card__title {
  148 + flex: 1;
  149 + min-width: 0;
  150 + font-size: 32rpx;
  151 + font-weight: 500;
  152 + color: #1F2937;
  153 + overflow: hidden;
  154 + white-space: nowrap;
  155 + text-overflow: ellipsis;
  156 +}
  157 +.plan-card .u-body-item {
  158 + margin-bottom: 12rpx;
  159 +}
162 160  
  161 +/* 照片区块 */
  162 +.photo-block {
  163 + margin-top: 16rpx;
  164 + padding-top: 16rpx;
  165 + border-top: 1rpx solid #E8EBF0;
  166 +}
163 167  
164 168 // 空文本样式
165 169 .empty-text {
166   - color: #999;
  170 + color: #909399;
167 171 font-size: 28rpx;
168 172 line-height: 80rpx;
169 173 display: block;
170 174 text-align: left;
171 175 }
172 176  
173   -// 优化uview组件样式
174   -:deep(.up-cell-group) {
175   - --u-cell-group-background-color: #fff;
176   - --u-cell-group-border-radius: 12rpx;
177   - --u-cell-group-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
178   -}
179   -
180   -:deep(.up-cell) {
181   - --u-cell-title-font-size: 28rpx;
182   - --u-cell-value-font-size: 28rpx;
183   - --u-cell-title-color: #666;
184   - --u-cell-value-color: #333;
185   - --u-cell-padding: 20rpx 15rpx;
186   - --u-cell-border-color: #f5f5f5;
187   -}
188   -
189 177 // 相册样式优化(关键:适配图片展示)
190 178 :deep(.up-album) {
191 179 width: 100%;
... ...
pages-sub/daily/maintain-manage/road-detail-list.vue
... ... @@ -7,9 +7,9 @@
7 7 <up-tabs
8 8 v-model="activeStatus"
9 9 :list="statusTabs"
10   - line-width="40rpx"
11   - active-color="#1989fa"
12   - inactive-color="#666"
  10 + line-width="44rpx"
  11 + active-color="#2563EB"
  12 + inactive-color="#4B5563"
13 13 :scrollable="true"
14 14 class="status-tabs"
15 15 @click="handleStatusChange"
... ... @@ -44,10 +44,15 @@
44 44 <template #empty>
45 45 <empty-view/>
46 46 </template>
47   - <view class="common-card-list" style=" padding-top: 170rpx;">
  47 + <view class="common-card-list plan-card-list">
48 48 <up-card
49 49 :border="false"
50 50 :foot-border-top="false"
  51 + :head-border-bottom="false"
  52 + margin="0"
  53 + padding-head="24rpx 24rpx 0"
  54 + padding-body="16rpx 24rpx 24rpx"
  55 + box-shadow="0 4rpx 16rpx rgba(17, 24, 39, 0.06)"
51 56 v-for="(item,index) in planList"
52 57 :key="`${item.planNo}_${index}`"
53 58 >
... ... @@ -55,6 +60,8 @@
55 60 <template #head>
56 61 <view class="card-header">
57 62 <view class="common-card-title common-name">{{ item.planName || '无计划名称' }}</view>
  63 + <!-- 待完成标识 -->
  64 + <view v-show="item.finishState == 1 " class="common-pending-tag">待完成</view>
58 65 <!-- 已失效标识 -->
59 66 <view v-show="item.finishState == 3 " class="common-invalid-tag">已失效</view>
60 67 <view v-show="item.finishState == 2 " class="common-finish-tag">已完成</view>
... ... @@ -76,14 +83,6 @@
76 83 <!-- </up-button>-->
77 84 <!-- </view>-->
78 85  
79   - <view class="common-custom-btn " v-if="item.finishState ==3" style="--btn-top: 100px;" >
80   - 补交记录
81   - </view>
82   - <view class="common-custom-btn " v-else style="--btn-top: 100px;" @click="submitRecord(item)">
83   - 提交记录
84   - </view>
85   -
86   -
87 86 <view class="u-body-item u-flex">
88 87 <view class="u-body-item-title">计划编码:</view>
89 88 <view class="u-line-1 u-body-value">{{ item.planNo || '-' }}</view>
... ... @@ -95,23 +94,13 @@
95 94 </view>
96 95 </view>
97 96  
98   - <view class="u-body-item u-flex common-item-center common-justify-between">
99   - <view class="u-body-item-title">计划完成次数: {{ item.planNum || 0 }}</view>
100   -<!-- <view class="">-->
101   -<!-- <up-button-->
102   -<!-- type="primary"-->
103   -<!-- size="mini"-->
104   -<!-- @click="submitRecord(item)"-->
105   -<!-- class="submit-record-btn"-->
106   -<!-- :disabled="item.finishState == 3"-->
107   -<!-- >-->
108   -<!-- {{ item.finishState ==3 ? '补交记录' : '提交记录' }}-->
109   -<!-- </up-button>-->
110   -<!-- </view>-->
  97 + <view class="u-body-item u-flex">
  98 + <view class="u-body-item-title">计划完成次数:</view>
  99 + <view class="u-line-1 u-body-value">{{ item.planNum || 0 }}</view>
111 100 </view>
112 101  
113 102 <view class="u-body-item u-flex">
114   - <view class="u-body-item-title">完成次数:</view>
  103 + <view class="u-body-item-title">已完成次数:</view>
115 104 <view class="u-line-1 u-body-value">{{ item.planFinishNum || 0 }}</view>
116 105 </view>
117 106  
... ... @@ -121,6 +110,12 @@
121 110 {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }}
122 111 </view>
123 112 </view>
  113 +
  114 + <!-- 操作区:统一收底 -->
  115 + <view class="card-action-row">
  116 + <view v-if="item.finishState ==3" class="mini-btn mini-btn--plain">补交记录</view>
  117 + <view v-else class="mini-btn mini-btn--primary" @click="submitRecord(item)">提交记录</view>
  118 + </view>
124 119 </view>
125 120 </template>
126 121 </up-card>
... ... @@ -221,20 +216,36 @@ onShow(() =&gt; {
221 216 </script>
222 217  
223 218 <style scoped lang="scss">
  219 +/* 页面底色:统一浅灰蓝(设计稿 --page-bg) */
224 220 .page-container {
  221 + min-height: 100vh;
  222 + background-color: #F4F6FA;
  223 + box-sizing: border-box;
225 224 }
226 225 // 顶部吸顶区域样式
  226 +/* 筛选条:Tabs(44px) + 搜索条上 8px / 左右 12px / 下 12px(设计稿 .tabs + .search-bar) */
227 227 .sticky-header {
228   - margin-top: -10rpx;
229 228 background-color: #ffffff;
230   - padding-bottom: 10rpx;
231   - border-bottom: 1px solid #eee;
  229 + padding-bottom: 24rpx;
  230 + border-bottom: 1rpx solid #E8EBF0;
232 231  
233 232 .search-input {
234   - margin: 20rpx 20rpx 10rpx !important;
  233 + margin: 16rpx 24rpx 0 !important;
235 234 }
236 235 }
237 236  
  237 +/* 卡片列表:页面左右 24rpx、卡片之间 24rpx(设计稿 .body)
  238 + * 顶部留白 = 吸顶筛选条高度(44+8+32+12=96px) + 12px 间距,避免卡片被吸顶区盖住 */
  239 +.plan-card-list {
  240 + display: flex;
  241 + flex-direction: column;
  242 + gap: 24rpx;
  243 + padding: 216rpx 24rpx 24rpx;
  244 +}
238 245  
  246 +/* 卡片体:内边距由 up-card 的 paddingBody 控制,此处不再叠加 */
  247 +.card-body {
  248 + padding: 0;
  249 +}
239 250  
240 251 </style>
241 252 \ No newline at end of file
... ...
pages-sub/daily/maintain-manage/type-list-page.vue
... ... @@ -2,8 +2,8 @@
2 2 <view class="page-container">
3 3 <up-sticky>
4 4 <view class="sticky-wrap">
5   - <up-tabs v-model="activeStatus" :list="statusTabs" line-width="40rpx" active-color="#1989fa"
6   - inactive-color="#666" :scrollable="false" @change="handleStatusChange"></up-tabs>
  5 + <up-tabs v-model="activeStatus" :list="statusTabs" line-width="44rpx" active-color="#2563EB"
  6 + inactive-color="#4B5563" :scrollable="false" @change="handleStatusChange"></up-tabs>
7 7 </view>
8 8 </up-sticky>
9 9 <z-paging ref="pagingRef" v-model="currentList" @query="fetchData" :auto-show-system-loading="true">
... ... @@ -12,43 +12,61 @@
12 12 </template>
13 13 <view class="card-list">
14 14 <view class="task-card" v-for="(item, index) in currentList" :key="`${item.planNo}_${index}`">
15   - <!-- 第一行:任务名称 + 置为失效 -->
16   - <view class="row row-1">
  15 + <!-- 计划名称 -->
  16 + <view class="card-head">
17 17 <view class="plan-name u-line-1">{{ item.planName || '无计划名称' }}</view>
18   - <!-- 权限:包含team_leader_yl / team_leader_wy / team_leader_hjws 并且当前是待完成tab,才显示置为失效 -->
19   - <view v-if="hasInvalidPerm && activeStatus === '1'" class="btn-set-invalid"
20   - @click.stop="handleSetInvalid(item)">
21   - 置为失效
22   - </view>
23 18 </view>
24   - <!-- 第二行:任务次数 + 去作业按钮 -->
25   - <view class="row row-2">
26   - <view class="info-text" v-if="activeStatus === '2'">完成次数:{{ item.planFinishNum }}次</view>
27   - <view class="info-text" v-else>任务次数:第{{ item.planFinishNum +1 }}次</view>
28   -
29   - <!-- 待完成:去作业;已完成:去查看 -->
30   - <view v-if="activeStatus === '1'" class="mini-btn" @click.stop="handleGoWork(item)">去作业</view>
31   - <view v-else-if="activeStatus === '2'" class="mini-btn" @click.stop="handleGoWorkLook(item)">去查看</view>
32   - <view v-else-if="activeStatus === '3'" class="mini-btn" @click.stop="handleGoWorkLook(item)">去查看</view>
  19 + <!-- 任务次数 -->
  20 + <view class="info-row">
  21 + <view class="info-label">任务次数</view>
  22 + <view class="info-value" v-if="activeStatus === '2'">完成 {{ item.planFinishNum }} 次</view>
  23 + <!-- 一次一条期次(planNum=1)时「第几次」取期次序号,历史多条次数的期次仍按完成次数递增 -->
  24 + <view class="info-value" v-else>第 {{ item.planNum === 1 ? (item.sortNum || 1) : (item.planFinishNum + 1) }} 次</view>
33 25 </view>
34   - <!-- 第三行:有效期 + 结束任务按钮 -->
35   - <view class="row row-3">
  26 + <!-- 有效期 -->
  27 + <view class="info-row">
36 28 <!-- timeFormat(start, 'yyyy-mm-dd'), -->
37   - <view class="info-text u-line-1">有效期:{{ timeFormat(item.beginTime, 'yyyy-mm-dd') }}—{{
  29 + <view class="info-label">有效期</view>
  30 + <view class="info-value u-line-1">{{ timeFormat(item.beginTime, 'yyyy-mm-dd') }}—{{
38 31 timeFormat(item.endTime, 'yyyy-mm-dd') }}
39 32 </view>
40   - <!-- ✅ 修改:去掉item.commitId判断,待完成tab就一直展示结束任务 -->
41   - <view v-if="activeStatus === '1'" class="mini-btn"
42   - @click.stop="handleEndTask(item)">结束任务</view>
  33 + </view>
  34 + <!-- 操作区:统一收底,与信息区用分隔线隔开 -->
  35 + <view class="action-row">
  36 + <!-- 待完成且一次都没上报过才允许置为失效;已有养护记录(进行中/已完成过)不再显示 -->
  37 + <view v-if="activeStatus === '1' && !hasReport(item)" class="mini-btn btn-brand-soft"
  38 + @click.stop="handleSetInvalid(item)">
  39 + 置为失效
  40 + </view>
  41 + <view class="action-right">
  42 + <!-- ✅ 修改:去掉item.commitId判断,待完成tab就一直展示结束任务 -->
  43 + <view v-if="activeStatus === '1'" class="mini-btn btn-brand-outline"
  44 + @click.stop="handleEndTask(item)">结束任务</view>
  45 + <!-- 待完成:去作业;已完成:去查看 -->
  46 + <view v-if="activeStatus === '1'" class="mini-btn btn-brand-solid" @click.stop="handleGoWork(item)">去作业</view>
  47 + <view v-else-if="activeStatus === '2'" class="mini-btn mini-btn--info" @click.stop="handleGoWorkLook(item)">去查看</view>
  48 + <view v-else-if="activeStatus === '3'" class="mini-btn mini-btn--info" @click.stop="handleGoWorkLook(item)">去查看</view>
  49 + </view>
43 50 </view>
44 51 </view>
45 52 </view>
46 53 </z-paging>
47   - <!-- ========== 置为失效 简单二次确认弹窗【修改后】 ========== -->
48   - <up-modal :show="invalidModalShow" title="提示" :closeOnClickOverlay="false" :showConfirmButton="true"
  54 + <!-- ========== 置为失效 弹窗(必须填写失效原因) ========== -->
  55 + <up-modal :show="invalidModalShow" title="置为失效" :closeOnClickOverlay="false" :showConfirmButton="true"
49 56 :showCancelButton="true" @cancel="handleInvalidModalCancel" @confirm="confirmSetInvalid">
50 57 <view class="invalid-modal-content">
51   - <text>确定置为失效吗?</text>
  58 + <view class="invalid-modal-label">
  59 + <text class="invalid-modal-required">*</text>
  60 + <text>失效原因</text>
  61 + </view>
  62 + <up-textarea v-model="invalidReason" placeholder="请输入失效原因" :maxlength="200" count
  63 + height="100" border="surround"></up-textarea>
  64 + <view class="invalid-modal-label">
  65 + <text>失效凭证(选填,最多3张)</text>
  66 + </view>
  67 + <up-upload :file-list="invalidImages" @after-read="uploadInvalidImgs"
  68 + @delete="deleteInvalidImg" @on-exceed="handleInvalidExceed" multiple :max-count="3"
  69 + upload-text="选择图片" del-color="#ff4d4f" class="upload-wrap"></up-upload>
52 70 </view>
53 71 </up-modal>
54 72 <!-- ========== 结束任务二次确认弹窗 ========== -->
... ... @@ -61,10 +79,10 @@
61 79 </view>
62 80 </template>
63 81 <script setup lang="ts">
64   -import { ref, computed } from 'vue'
  82 +import { ref } from 'vue'
65 83 import { onShow, onUnload, onLoad } from '@dcloudio/uni-app'
66   -import { useUserStore } from '@/pinia/user';
67 84 import { maintainPlanNum, finishPlan, invalidatePlan, maintainCreate } from "@/api/maintain-manage/maintain-manage";
  85 +import { uploadImages } from '@/common/utils/upload';
68 86 import { timeFormat } from '@/uni_modules/uview-plus';
69 87 /** 获取当天日期 yyyy-MM-dd */
70 88 const getTodayStr = () => {
... ... @@ -74,14 +92,9 @@ const getTodayStr = () =&gt; {
74 92 const day = String(d.getDate()).padStart(2, '0')
75 93 return `${year}-${month}-${day}`
76 94 }
77   -const userStore = useUserStore();
78   -const userRoles = computed<string[]>(() => userStore.userInfo?.roles || []);
79   -// 判断是否拥有置为失效权限:任意一个组长角色就可以
80   -const hasInvalidPerm = computed(() => {
81   - const roles = userRoles.value
82   - const leaderRoles = ['team_leader_yl', 'team_leader_wy', 'team_leader_hjws']
83   - return leaderRoles.some(key => roles.includes(key))
84   -})
  95 +// 是否已经上报过:有进行中的上报(commitId)或已推进过完成次数(planFinishNum>0)
  96 +// 有养护记录的任务不允许置为失效
  97 +const hasReport = (item: any) => !!item?.commitId || Number(item?.planFinishNum || 0) > 0
85 98 const statusTabs = ref([
86 99 { name: '待完成', id: '1' },
87 100 { name: '已失效', id: '3' },
... ... @@ -97,6 +110,10 @@ const allTotalData = ref&lt;any[]&gt;([])
97 110 // ===================== 失效弹窗状态 =====================
98 111 const invalidModalShow = ref(false)
99 112 const currentInvalidItem = ref(null)
  113 +// 失效原因(必填,提交时作为 invalidReason 传给后端)
  114 +const invalidReason = ref('')
  115 +// 失效凭证(选填,最多 3 张,上传成功后取 url 作为 invalidFiles)
  116 +const invalidImages = ref<any[]>([])
100 117 // ===================== 结束任务确认弹窗 =====================
101 118 const endTaskModalShow = ref(false)
102 119 const currentEndTaskItem = ref<any>(null)
... ... @@ -104,6 +121,9 @@ const currentEndTaskItem = ref&lt;any&gt;(null)
104 121 const loadData = async () => {
105 122 console.log('123123')
106 123 if (!originRawList || originRawList.length === 0) {
  124 + // 没有批次时要显式结束分页,否则 z-paging 收不到 complete,页面一直停在加载中
  125 + allTotalData.value = []
  126 + pagingRef.value?.complete([], 0)
107 127 return
108 128 }
109 129 uni.showLoading({ title: '加载数据...', mask: true })
... ... @@ -179,12 +199,60 @@ const handleStatusChange = async (tabItem) =&gt; {
179 199 // 打开失效弹窗
180 200 const handleSetInvalid = (item) => {
181 201 currentInvalidItem.value = item
  202 + invalidReason.value = ''
  203 + invalidImages.value = []
182 204 invalidModalShow.value = true
183 205 }
184 206 // 关闭弹窗,重置数据
185 207 const handleInvalidModalCancel = () => {
186 208 invalidModalShow.value = false
187 209 currentInvalidItem.value = null
  210 + invalidReason.value = ''
  211 + invalidImages.value = []
  212 +}
  213 +// 失效凭证上传(最多 3 张,与 add-record 的图片上传保持一致)
  214 +const uploadInvalidImgs = async (event: any) => {
  215 + const fileList = Array.isArray(event.file) ? event.file : [event.file]
  216 + const validFiles = fileList.filter((item: any) => item && item.url)
  217 + if (!validFiles.length) return
  218 + const startIndex = invalidImages.value.length
  219 + invalidImages.value.push(...validFiles.map((item: any) => ({ ...item, status: 'uploading', message: '上传中' })))
  220 + try {
  221 + const urls = await uploadImages({ filePaths: validFiles.map((item: any) => item.url), ignoreError: true })
  222 + urls.forEach((url: string, index: number) => {
  223 + if (invalidImages.value[startIndex + index]) {
  224 + invalidImages.value.splice(startIndex + index, 1, {
  225 + ...validFiles[index], status: 'success', message: '', url
  226 + })
  227 + }
  228 + })
  229 + for (let i = urls.length; i < validFiles.length; i++) {
  230 + if (invalidImages.value[startIndex + i]) {
  231 + invalidImages.value.splice(startIndex + i, 1, {
  232 + ...validFiles[i], status: 'failed', message: '上传失败'
  233 + })
  234 + }
  235 + }
  236 + if (urls.length < validFiles.length) {
  237 + uni.showToast({ title: `成功上传${urls.length}张,失败${validFiles.length - urls.length}张`, icon: 'none' })
  238 + }
  239 + } catch (err) {
  240 + console.error('失效凭证上传失败:', err)
  241 + for (let i = 0; i < validFiles.length; i++) {
  242 + if (invalidImages.value[startIndex + i]) {
  243 + invalidImages.value.splice(startIndex + i, 1, {
  244 + ...validFiles[i], status: 'failed', message: '上传失败'
  245 + })
  246 + }
  247 + }
  248 + uni.showToast({ title: '图片上传失败,请重试', icon: 'none' })
  249 + }
  250 +}
  251 +const deleteInvalidImg = (event: any) => {
  252 + invalidImages.value.splice(event.index, 1)
  253 +}
  254 +const handleInvalidExceed = () => {
  255 + uni.showToast({ title: '最多只能上传3张图片', icon: 'none' })
188 256 }
189 257 // 确认提交置为失效
190 258 const confirmSetInvalid = async () => {
... ... @@ -194,6 +262,20 @@ const confirmSetInvalid = async () =&gt; {
194 262 uni.showToast({ title: '数据异常', icon: 'none', duration:2000 })
195 263 return
196 264 }
  265 + // 失效原因必填:为空时不关闭弹窗、不发起任何请求
  266 + const reason = (invalidReason.value || '').trim()
  267 + if (!reason) {
  268 + uni.showToast({ title: '请填写失效原因', icon: 'none', duration:2000 })
  269 + return
  270 + }
  271 + // 图片还在上传时不能提交,否则会把空 url 或本地路径传给后端
  272 + if (invalidImages.value.some((file: any) => file.status === 'uploading')) {
  273 + uni.showToast({ title: '图片上传中,请稍候', icon: 'none', duration:2000 })
  274 + return
  275 + }
  276 + const invalidFiles = invalidImages.value
  277 + .filter((file: any) => file.status === 'success' && file.url)
  278 + .map((file: any) => file.url)
197 279 uni.showLoading({ title: '提交中...', mask: true })
198 280 try {
199 281 let targetCommitId = item.commitId
... ... @@ -217,8 +299,10 @@ const confirmSetInvalid = async () =&gt; {
217 299 }
218 300 const params = {
219 301 commitId: targetCommitId,
220   - invalidReason: '管理员手动置为失效',
221   - invalidFiles: ''
  302 + // 使用弹窗中填写的原因(必填),不再写死默认文案
  303 + invalidReason: reason,
  304 + // 后端 invalidFiles 是 List<String>,无图时传空数组
  305 + invalidFiles
222 306 }
223 307 console.log('置为失效提交参数:', params)
224 308 await invalidatePlan(params)
... ... @@ -265,23 +349,13 @@ const confirmEndTask = async () =&gt; {
265 349 endTaskModalShow.value = false
266 350 uni.showLoading({ title: '提交中...', mask: true })
267 351 try {
268   - let targetCommitId = item.commitId
269   - // 不存在commitId,先创建草稿
  352 + const targetCommitId = item.commitId
  353 + // 没有进行中的上报说明本次还没作业:后端结束任务要求至少一条正常作业记录,
  354 + // 先建草稿再结束必定失败,还会留下一条永远「进行中」的脏草稿,这里直接拦下。
270 355 if (!targetCommitId) {
271   - const submitData = {
272   - planNo: item.planNo,
273   - imgHost: '1',
274   - beginImg: [],
275   - commonUserList: [],
276   - remark: ''
277   - }
278   - const createRes: any = await maintainCreate(submitData)
279   - targetCommitId = createRes && typeof createRes === 'object' ? createRes.id : createRes
280   - if (!targetCommitId) {
281   - uni.hideLoading()
282   - uni.showToast({ title: '创建养护草稿失败,无法结束任务', icon: 'none', duration:2000 })
283   - return
284   - }
  356 + uni.hideLoading()
  357 + uni.showToast({ title: '请先添加作业记录后再结束任务', icon: 'none', duration: 2000 })
  358 + return
285 359 }
286 360 await finishPlan({ commitId: targetCommitId })
287 361 uni.hideLoading()
... ... @@ -305,61 +379,122 @@ onUnload(() =&gt; {
305 379 <style scoped lang="scss">
306 380 .page-container {
307 381 height: 100vh;
308   - background-color: #f5f5f5;
  382 + background-color: #F4F6FA;
309 383 }
310 384 .sticky-wrap {
311 385 background: #fff;
312   - border-bottom: 1rpx solid #eee;
  386 + border-bottom: 1rpx solid #E8EBF0;
313 387 }
  388 +/* 卡片列表:页面左右 24rpx、卡片之间 24rpx(设计稿 .body)
  389 + * 顶部留白 = 吸顶 Tabs 高度 + 12px 间距,z-paging 内容从容器顶部起算,
  390 + * 不留这段会被吸顶 Tabs 盖住卡片标题(与原页面 padding-top:100rpx 等效) */
314 391 .card-list {
315   - padding: 100rpx 20rpx 20rpx;
  392 + padding: 112rpx 24rpx 24rpx;
316 393 display: flex;
317 394 flex-direction: column;
318   - gap: 20rpx;
  395 + gap: 24rpx;
319 396 }
  397 +/* 卡片:12px 内边距 / 8px 圆角 / 卡片阴影(设计稿 .tcard) */
320 398 .task-card {
321 399 background: #fff;
322   - border-radius: 12rpx;
  400 + border-radius: 16rpx;
323 401 padding: 24rpx;
  402 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
324 403 display: flex;
325 404 flex-direction: column;
326   - gap: 20rpx;
327 405 }
328   -.row {
  406 +/* 标题行:标题占满剩余宽度,状态标签靠右(设计稿 .tcard-head) */
  407 +.card-head {
329 408 display: flex;
330 409 align-items: center;
331   - justify-content: space-between;
332 410 gap: 16rpx;
  411 + margin-bottom: 16rpx;
333 412 }
334 413 .plan-name {
335   - font-size: 30rpx;
336   - color: #333;
337   - font-weight: 500;
338 414 flex: 1;
  415 + min-width: 0;
  416 + font-size: 32rpx;
  417 + color: #1F2937;
  418 + font-weight: 500;
  419 + line-height: 1.4;
339 420 }
340   -.btn-set-invalid {
  421 +.info-row {
  422 + display: flex;
  423 + align-items: center;
  424 + justify-content: space-between;
  425 + gap: 16rpx;
  426 + margin-bottom: 6rpx;
  427 +}
  428 +.info-label {
341 429 font-size: 26rpx;
342   - color: #1677ff;
  430 + color: #9CA3AF;
343 431 flex-shrink: 0;
344   - padding-left: 16rpx;
345 432 }
346   -.info-text {
347   - font-size: 26rpx;
348   - color: #666;
  433 +.info-value {
349 434 flex: 1;
  435 + min-width: 0;
  436 + font-size: 26rpx;
  437 + color: #4B5563;
  438 + text-align: right;
350 439 }
351   -.mini-btn {
352   - font-size: 24rpx;
353   - color: #333;
354   - background: #f5f5f5;
355   - border: 1rpx solid #ddd;
356   - border-radius: 6rpx;
357   - padding: 8rpx 20rpx;
358   - flex-shrink: 0;
  440 +/* 操作区统一收底:上 16rpx 留白 + 分隔线(设计稿 .tcard-foot) */
  441 +.action-row {
  442 + display: flex;
  443 + align-items: center;
  444 + justify-content: space-between;
  445 + gap: 16rpx;
  446 + margin-top: 16rpx;
  447 + padding-top: 16rpx;
  448 + border-top: 1rpx solid #E8EBF0;
  449 +}
  450 +.action-right {
  451 + display: flex;
  452 + align-items: center;
  453 + gap: 16rpx;
  454 + margin-left: auto;
  455 +}
  456 +// 置为失效(红字)/ 去作业(蓝)/ 去查看(灰)/ 结束任务(白底描边)
  457 +// 尺寸与配色统一由全局 .btn-text-danger、.mini-btn 系列控制
  458 +/* 卡片操作按钮:统一按钮形态,主色 #3b9dff
  459 + * 浅底(置为失效) / 描边(结束任务) / 实心(去作业)
  460 + * 需 !important 覆盖全局 .mini-btn 的白字与 .btn-text-danger 等既有配色 */
  461 +.btn-brand-soft {
  462 + color: #3b9dff !important;
  463 + background-color: #EAF4FF !important;
  464 +}
  465 +
  466 +.btn-brand-outline {
  467 + color: #3b9dff !important;
  468 + background-color: #ffffff !important;
  469 + border: 1rpx solid #3b9dff;
  470 +}
  471 +
  472 +.btn-brand-solid {
  473 + color: #ffffff !important;
  474 + background-color: #3b9dff !important;
359 475 }
360 476 .invalid-modal-content {
361 477 width: 100%;
362 478 box-sizing: border-box;
363 479 padding: 10rpx 0;
364 480 }
  481 +
  482 +/* 失效原因(必填):标签 + 输入域 */
  483 +.invalid-modal-label {
  484 + display: flex;
  485 + align-items: center;
  486 + gap: 6rpx;
  487 + margin-bottom: 16rpx;
  488 + font-size: 28rpx;
  489 + color: #1F2937;
  490 +}
  491 +
  492 +.invalid-modal-required {
  493 + color: #DC2626;
  494 +}
  495 +
  496 +/* 失效凭证上传:与上方原因输入框保持同样的间距 */
  497 +.upload-wrap {
  498 + margin-top: 16rpx;
  499 +}
365 500 </style>
... ...
pages-sub/daily/maintain-manage/type-list.vue
1 1 <template>
2   - <view class="tag-wrap">
3   - <!-- 动态渲染标签列表 -->
  2 + <view class="type-grid">
  3 + <!-- 动态渲染养护类型卡片 -->
4 4 <template v-if="tagList.length > 0">
5   - <view class="tag-item" v-for="(item, idx) in tagList" :key="idx" hover-class="tag-item--hover"
  5 + <view class="type-card" v-for="(item, idx) in tagList" :key="idx" hover-class="type-card--hover"
6 6 @click="toNextPage(item)">
7   - <view class="tag-text">
8   - <!-- 文字区域:超长省略号,数字括号单独放后面,永远可见 -->
9   - <text class="tag-name">{{ item.planTypeName }}</text>
10   - <text class="tag-count">({{ item.todayPendingCount }})</text>
  7 + <!-- 类型图标:取类型名称首字,底色淡蓝 -->
  8 + <view class="type-icon">{{ (item.planTypeName || '养护').charAt(0) }}</view>
  9 + <view class="type-name">{{ item.planTypeName }}</view>
  10 + <view class="type-foot">
  11 + <text class="type-foot-label">待完成任务</text>
  12 + <text class="type-count">{{ item.todayPendingCount }}</text>
11 13 </view>
12 14 </view>
13 15 </template>
14 16 <template v-else>
15   - <view style="padding-top: 30px;text-align: center;width: 100%;">暂无养护类型,请去平台配置</view>
  17 + <view class="type-empty">暂无养护类型,请去平台配置</view>
16 18 </template>
17 19 </view>
18 20 </template>
... ... @@ -55,42 +57,94 @@ onUnload(()=&gt;{
55 57 })
56 58 </script>
57 59 <style scoped lang="scss">
58   -.tag-wrap {
59   - display: flex;
60   - flex-wrap: wrap;
61   - gap: 24rpx;
62   - padding: 30rpx;
  60 +/* 两列卡片栅格:页面 24rpx 内边距,卡片间距 16rpx(设计稿 .type-grid) */
  61 +.type-grid {
  62 + display: grid;
  63 + grid-template-columns: 1fr 1fr;
  64 + gap: 16rpx;
  65 + padding: 24rpx;
63 66 }
64   -.tag-item {
65   - display: inline-flex;
66   - align-items: center;
67   - background: #e8f3ff;
68   - border: 1rpx solid #94c5ff;
69   - border-radius: 8rpx;
70   - padding: 16rpx 24rpx;
71   - max-width: 320rpx;
72   - transition: all 0.2s;
  67 +
  68 +/* 卡片:12px 内边距 / 8px 圆角 / 8rpx 内部行距(设计稿 .type-card) */
  69 +.type-card {
  70 + display: flex;
  71 + flex-direction: column;
  72 + box-sizing: border-box;
  73 + gap: 8rpx;
  74 + background: #ffffff;
  75 + border-radius: 16rpx;
  76 + padding: 24rpx;
  77 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  78 + transition: background-color 0.15s ease;
  79 +
73 80 &--hover {
74   - background: #d8eaff;
  81 + background: #F4F5F7;
75 82 }
76 83 }
77   -.tag-text {
  84 +
  85 +/* 类型图标位:68rpx 方块 + 淡蓝底(设计稿 .type-ico) */
  86 +.type-icon {
78 87 display: flex;
79 88 align-items: center;
80   - flex: 1;
81   - overflow: hidden;
  89 + justify-content: center;
  90 + width: 68rpx;
  91 + height: 68rpx;
  92 + background: #EBF3FF;
  93 + border-radius: 8rpx;
  94 + font-size: 30rpx;
  95 + font-weight: 600;
  96 + color: #2563EB;
  97 + line-height: 1;
82 98 }
83   -.tag-name {
  99 +
  100 +/* 类型名称:14px / 500(设计稿 .type-card 标题) */
  101 +.type-name {
  102 + font-size: 28rpx;
  103 + font-weight: 500;
  104 + color: #1F2937;
  105 + line-height: 1.4;
84 106 white-space: nowrap;
85 107 overflow: hidden;
86 108 text-overflow: ellipsis;
87   - color: #1677ff;
88   - font-size: 28rpx;
89 109 }
90   -.tag-count {
91   - color: #1677ff;
92   - font-size: 28rpx;
  110 +
  111 +/* 底部统计行:左侧说明 11px 浅灰,右侧数量标签(设计稿 .type-meta) */
  112 +.type-foot {
  113 + display: flex;
  114 + align-items: center;
  115 + justify-content: space-between;
  116 + margin-top: auto;
  117 + font-size: 22rpx;
  118 + color: #9CA3AF;
  119 +}
  120 +
  121 +.type-foot-label {
  122 + font-size: 22rpx;
  123 + color: #9CA3AF;
  124 + line-height: 1.5;
  125 +}
  126 +
  127 +/* 数量标签:灰底胶囊(设计稿 .tag.gray) */
  128 +.type-count {
  129 + display: inline-flex;
  130 + align-items: center;
93 131 flex-shrink: 0;
94   - margin-left: 4rpx;
  132 + height: 40rpx;
  133 + padding: 0 16rpx;
  134 + background: #F4F6FA;
  135 + border-radius: 8rpx;
  136 + font-size: 22rpx;
  137 + font-weight: 500;
  138 + color: #4B5563;
  139 + line-height: 1;
  140 +}
  141 +
  142 +/* 空状态 */
  143 +.type-empty {
  144 + grid-column: 1 / -1;
  145 + padding-top: 60rpx;
  146 + font-size: 26rpx;
  147 + color: #9CA3AF;
  148 + text-align: center;
95 149 }
96 150 </style>
... ...
pages-sub/daily/patrol-manage/add-patrol-record.vue
1 1 <template>
2 2 <view class="u-page">
3 3 <!-- 原有模板内容不变,仅调整表单校验相关配置 -->
4   - <view class="inspect-form-content commonPageLRpadding">
  4 + <view class="inspect-form-content">
5 5 <up-form label-position="left" :model="inspectForm" ref="inspectFormRef" labelWidth="200rpx">
6   - <!-- 1. 巡查描述 -->
7   - <up-form-item label="巡查描述" prop="content" class="form-item" required>
8   - <up-textarea v-model.trim="inspectForm.content" placeholder="请输入巡查描述" maxlength="200" count></up-textarea>
9   - </up-form-item>
10   - <!-- 2. 上传图片 -->
11   - <up-form-item label="上传图片" prop="images" required border-bottom class="form-item">
12   - <up-upload :file-list="imagesList" @after-read="(event) => uploadImgs(event)"
13   - @delete="(event) => deleteImg(event)" @on-exceed="handleExceed" multiple :max-count="3" upload-text="选择图片"
14   - del-color="#ff4d4f" class="upload-wrap" width="70" height="70"></up-upload>
15   - </up-form-item>
16   - <!-- 3. 转为工单 -->
17   - <up-form-item label="转为工单" prop="isWorkOrder" required class="form-item">
18   - <up-radio-group v-model="inspectForm.isWorkOrder" active-color="#1989fa" direction="row" class="radio-group"
19   - @change="handleWorkOrderChange">
20   - <up-radio :custom-style="{ marginRight: '40rpx' }" v-for="(item, index) in radioList" :key="index"
21   - :label="item.label" :name="item.value">
22   - {{ item.label }}
23   - </up-radio>
24   - </up-radio-group>
25   - </up-form-item>
26   - <!-- ========== 【新增】业务线(单选框,对齐参考页面) ========== -->
27   - <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="业务线" prop="busiLineCn" border-bottom required
28   - class="form-item">
29   - <up-radio-group v-model="inspectForm.busiLineCn" placement="row" @change="handleBusiLineChange">
30   - <up-radio v-for="item in busiLineOptions" :key="item.name" :label="item.name" :name="item.name"></up-radio>
31   - </up-radio-group>
32   - </up-form-item>
33   - <!-- ========== 【新增】问题类型(级联选择器,对齐参考页面) ========== -->
34   - <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="问题类型" prop="orderName" border-bottom required
35   - class="form-item" @click="openCascader(); uni.hideKeyboard()">
36   - <up-input v-model="inspectForm.orderName" disabled disabled-color="#ffffff" placeholder="请选择问题类型"
37   - border="none"></up-input>
38   - <template #right>
39   - <up-icon name="arrow-right" size="16"></up-icon>
40   - </template>
41   - </up-form-item>
42   - <!-- 紧急程度(仍为必填) -->
43   - <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="紧急程度" prop="pressingTypeName" border-bottom required
44   - class="form-item" @click="handleActionSheetOpen('pressingType')">
45   - <up-input v-model="inspectForm.pressingTypeName" disabled disabled-color="#ffffff" placeholder="请选择紧急程度"
46   - border="none"></up-input>
47   - <template #right>
48   - <up-icon name="arrow-right" size="16"></up-icon>
49   - </template>
50   - </up-form-item>
51   - <!-- 希望完成时间(移除 required 属性,改为非必填) -->
52   - <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="希望完成时间" prop="expectedFinishDate" class="form-item"
53   - @click="show = true; uni.hideKeyboard()">
54   - <up-input v-model="inspectForm.expectedFinishDate" border="none" readonly placeholder="点击选择时间">
55   - </up-input>
56   - <template #right>
57   - <!-- 核心修复:用view包裹图标,添加双重@click.stop -->
58   - <view v-if="inspectForm.expectedFinishDate" @click.stop>
59   - <up-icon name="close" size="16" @click.stop="clearExpectedFinishDate"></up-icon>
60   - </view>
61   - <up-icon name="arrow-right" size="16" v-else></up-icon>
62   - </template>
63   - </up-form-item>
  6 + <!-- 巡查信息 -->
  7 + <view class="form-card form-card--field">
  8 + <view class="sec-head">
  9 + <view class="sec-bar"></view>
  10 + <view class="sec-title">巡查信息</view>
  11 + </view>
  12 + <!-- 1. 巡查描述 -->
  13 + <up-form-item label="巡查描述" prop="content" class="form-item" required>
  14 + <up-textarea v-model.trim="inspectForm.content" placeholder="请输入巡查描述" maxlength="200" count></up-textarea>
  15 + </up-form-item>
  16 + </view>
  17 +
  18 + <!-- 作业信息 -->
  19 + <view class="form-card">
  20 + <view class="sec-head">
  21 + <view class="sec-bar"></view>
  22 + <view class="sec-title">作业信息</view>
  23 + </view>
  24 + <!-- 3. 转为工单 -->
  25 + <up-form-item label="转为工单" prop="isWorkOrder" required border-bottom class="form-item">
  26 + <up-radio-group v-model="inspectForm.isWorkOrder" active-color="#2563EB" direction="row" class="radio-group"
  27 + @change="handleWorkOrderChange">
  28 + <up-radio :custom-style="{ marginRight: '40rpx' }" v-for="(item, index) in radioList" :key="index"
  29 + :label="item.label" :name="item.value">
  30 + {{ item.label }}
  31 + </up-radio>
  32 + </up-radio-group>
  33 + </up-form-item>
  34 + <!-- ========== 【新增】业务线(单选框,对齐参考页面) ========== -->
  35 + <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="业务线" prop="busiLineCn" border-bottom required
  36 + class="form-item">
  37 + <up-radio-group v-model="inspectForm.busiLineCn" placement="row" @change="handleBusiLineChange">
  38 + <up-radio v-for="item in busiLineOptions" :key="item.name" :label="item.name" :name="item.name"></up-radio>
  39 + </up-radio-group>
  40 + </up-form-item>
  41 + <!-- ========== 【新增】问题类型(级联选择器,对齐参考页面) ========== -->
  42 + <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="问题类型" prop="orderName" border-bottom required
  43 + class="form-item" @click="openCascader(); uni.hideKeyboard()">
  44 + <up-input v-model="inspectForm.orderName" disabled disabled-color="#ffffff" placeholder="请选择问题类型"
  45 + border="none"></up-input>
  46 + <template #right>
  47 + <up-icon name="arrow-right" size="16"></up-icon>
  48 + </template>
  49 + </up-form-item>
  50 + <!-- 紧急程度(仍为必填) -->
  51 + <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="紧急程度" prop="pressingTypeName" border-bottom required
  52 + class="form-item" @click="handleActionSheetOpen('pressingType')">
  53 + <up-input v-model="inspectForm.pressingTypeName" disabled disabled-color="#ffffff" placeholder="请选择紧急程度"
  54 + border="none"></up-input>
  55 + <template #right>
  56 + <up-icon name="arrow-right" size="16"></up-icon>
  57 + </template>
  58 + </up-form-item>
  59 + <!-- 希望完成时间(移除 required 属性,改为非必填) -->
  60 + <up-form-item v-if="inspectForm.isWorkOrder === '2'" label="希望完成时间" prop="expectedFinishDate" class="form-item"
  61 + @click="show = true; uni.hideKeyboard()">
  62 + <up-input v-model="inspectForm.expectedFinishDate" border="none" readonly placeholder="点击选择时间">
  63 + </up-input>
  64 + <template #right>
  65 + <!-- 核心修复:用view包裹图标,添加双重@click.stop -->
  66 + <view v-if="inspectForm.expectedFinishDate" @click.stop>
  67 + <up-icon name="close" size="16" @click.stop="clearExpectedFinishDate"></up-icon>
  68 + </view>
  69 + <up-icon name="arrow-right" size="16" v-else></up-icon>
  70 + </template>
  71 + </up-form-item>
  72 + </view>
  73 +
  74 + <!-- 上传图片 -->
  75 + <view class="form-card form-card--field">
  76 + <view class="sec-head">
  77 + <view class="sec-bar"></view>
  78 + <view class="sec-title">上传图片</view>
  79 + </view>
  80 + <!-- 2. 上传图片 -->
  81 + <up-form-item label="上传图片" prop="images" required class="form-item">
  82 + <up-upload :file-list="imagesList" @after-read="(event) => uploadImgs(event)"
  83 + @delete="(event) => deleteImg(event)" @on-exceed="handleExceed" multiple :max-count="3" upload-text="选择图片"
  84 + del-color="#ff4d4f" class="upload-wrap" width="70" height="70"></up-upload>
  85 + <view class="upload-hint">最少 1 张 · 最多 3 张</view>
  86 + </up-form-item>
  87 + </view>
64 88 </up-form>
65 89 </view>
66 90 <!-- 底部提交按钮 -->
67 91 <view class="fixed-bottom-btn-wrap">
68   - <up-button type="primary" text="提交" @click="submitInspect"
69   - :style="{ width: '100%', height: '88rpx', fontSize: '32rpx', borderRadius: 0 }"></up-button>
  92 + <up-button type="primary" text="提交" @click="submitInspect"></up-button>
70 93 </view>
71 94 <!-- 紧急程度下拉弹窗 -->
72 95 <up-action-sheet :show="showActionSheet" :actions="pressingTypeList" title="请选择紧急程度" @close="handleActionSheetClose"
... ... @@ -470,14 +493,114 @@ export default {
470 493 <style lang="scss" scoped>
471 494 .u-page {
472 495 min-height: 100vh;
  496 + padding-bottom: 200rpx;
  497 + background-color: #F4F6FA;
  498 + box-sizing: border-box;
473 499 }
474 500  
475 501 .inspect-form-content {
476   - background: #fff;
477   - padding: 20rpx;
  502 + padding: 0 24rpx;
  503 + background: transparent;
478 504 }
479 505  
480 506 .form-item {
481 507 margin-bottom: 20rpx;
482 508 }
  509 +
  510 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  511 +.form-card {
  512 + margin-top: 24rpx;
  513 + padding: 8rpx 24rpx;
  514 + background-color: #ffffff;
  515 + border-radius: 16rpx;
  516 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  517 +}
  518 +
  519 +// 区块标题:蓝色竖条 + 标题文字
  520 +.sec-head {
  521 + display: flex;
  522 + align-items: center;
  523 + gap: 12rpx;
  524 + padding: 20rpx 0 8rpx;
  525 +}
  526 +.sec-bar {
  527 + width: 6rpx;
  528 + height: 28rpx;
  529 + background-color: #2563EB;
  530 + border-radius: 3rpx;
  531 +}
  532 +.sec-title {
  533 + font-size: 30rpx;
  534 + font-weight: 500;
  535 + color: #1F2937;
  536 +}
  537 +
  538 +// 表单行:上下 24rpx(左右由卡片内边距控制)
  539 +.form-card .form-item {
  540 + margin-bottom: 0;
  541 +}
  542 +.form-card :deep(.u-form-item__body) {
  543 + padding: 24rpx 0 !important;
  544 +}
  545 +.form-card :deep(.u-form-item__body__left__content__label) {
  546 + font-size: 28rpx;
  547 + color: #333333;
  548 +}
  549 +.form-card :deep(.u-line) {
  550 + background-color: #EEF1F6;
  551 +}
  552 +/* 卡片内最后一行不画分隔线 */
  553 +.form-card :deep(.u-form-item:last-child .u-line) {
  554 + display: none;
  555 +}
  556 +
  557 +/* 巡查描述 / 上传图片:分区标题已说明字段,隐藏左侧标签、内容整行铺满 */
  558 +.form-card--field :deep(.u-form-item__body__left) {
  559 + display: none;
  560 +}
  561 +.form-card--field :deep(.u-form-item__body__right) {
  562 + flex: 1;
  563 +}
  564 +.form-card--field :deep(.u-form-item__body) {
  565 + padding: 16rpx 0 24rpx;
  566 +}
  567 +/* 文本域:浅灰圆角输入区 */
  568 +.form-card--field :deep(.u-textarea) {
  569 + padding: 20rpx 20rpx 4rpx;
  570 + background-color: #F5F7FA;
  571 + border-radius: 12rpx;
  572 +}
  573 +.form-card--field :deep(.u-textarea__count) {
  574 + color: #9CA3AF;
  575 +}
  576 +/* 上传:虚线框 */
  577 +.form-card--field :deep(.u-upload__button) {
  578 + background-color: #FAFBFC;
  579 + border: 1rpx dashed #C8D2E0;
  580 + border-radius: 12rpx;
  581 +}
  582 +.upload-hint {
  583 + margin-top: 16rpx;
  584 + font-size: 24rpx;
  585 + color: #9CA3AF;
  586 +}
  587 +
  588 +/* 底部提交栏 */
  589 +.fixed-bottom-btn-wrap {
  590 + position: fixed;
  591 + left: 0;
  592 + right: 0;
  593 + bottom: 0;
  594 + z-index: 999;
  595 + padding: 16rpx 24rpx;
  596 + padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
  597 + background-color: #ffffff;
  598 + box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
  599 + box-sizing: border-box;
  600 +}
  601 +.fixed-bottom-btn-wrap :deep(.u-button) {
  602 + height: 88rpx !important;
  603 + border-radius: 16rpx !important;
  604 + font-size: 30rpx !important;
  605 +}
483 606 </style>
... ...
pages-sub/daily/patrol-manage/finish-plan-detail.vue
... ... @@ -5,93 +5,61 @@
5 5 v-if="loading"
6 6 :loading="true"
7 7 title="加载中..."
8   - color="#3c9cff"
  8 + color="#2563EB"
9 9 ></up-loading-page>
10 10  
11 11 <!-- 内容容器 -->
12 12 <template v-else>
13   - <view v-if="orderDetail.length>0">
14   - <view class="content-wrap" v-for="(i, index) in orderDetail" :key="index">
15   - <!-- 工单详情内容 -->
16   - <up-cell-group :border="false" inset >
17   -
18   - <up-cell
19   - align="middle"
20   - >
21   - <template #title>
22   - <view class="up-line-1">{{i.planName || '--'}}</view>
23   - </template>
24   - <!-- <template #value>-->
25   - <!-- <view class="up-line-1">{{orderDetail.planName || '&#45;&#45;'}}</view>-->
26   - <!-- </template>-->
27   - </up-cell>
28   -
29   - <!-- 2. 工单位置 -->
30   - <up-cell
31   - title="计划编码"
32   - :value="i.planNo || '--'"
33   - align="middle"
34   - ></up-cell>
35   -
36   -
37   - <up-cell
38   - title="养护周期"
39   - :value="`${i.rate}${uni.$dict.getDictLabel('cycle_id_type', i.cycleId)}`"
40   - align="middle"
41   - ></up-cell>
42   -
43   - <!-- 4. 情况描述 -->
44   - <up-cell
45   - title="计划有效期"
46   - :value="`${timeFormat(i.beginTime,'yyyy-mm-dd')} 至 ${timeFormat(i. endTime,'yyyy-mm-dd')}`"
47   - align="middle"
48   - ></up-cell>
49   -
50   - <!-- 5. 问题照片(核心修复:判断条件+空值处理) -->
51   - <up-cell title="照片">
52   - <template #value>
53   - <view class="cell-content-wrap">
54   -
55   - <!-- 修复1:正确判断problemImgsList,补充空数组默认值 -->
56   - <up-album
57   - v-if="!!i.imgList?.length"
58   - :urls="i.imgList || []"
59   - singleSize="70"
60   - :preview-full-image="true"
61   -
62   - ></up-album>
63   - <text v-else class="empty-text">暂无问题照片</text>
64   - </view>
65   - </template>
66   - </up-cell>
67   -
68   - <!-- 7. 处理结果 -->
69   - <up-cell
70   - align="middle"
71   - >
72   - <template #title>
73   - <view style="min-width: 200rpx">巡查描述</view>
74   - </template>
75   - <template #value>
76   - <view class="up-line-1 common-text-color">{{i.remark || '--'}}</view>
77   - </template>
78   - </up-cell>
79   -
80   - <up-cell
81   - title="提交时间"
82   - :value="i.finishTime==null?'--':timeFormat(i.finishTime,'yyyy-mm-dd hh:MM:ss') "
83   - align="middle"
84   -
85   - ></up-cell>
86   -
87   - <up-cell
88   - title="提交人"
89   - :value="i.userName || '--'"
90   - align="middle"
91   - :border="false"
92   - ></up-cell>
93   - </up-cell-group>
94   -
  13 + <view v-if="orderDetail.length>0" class="page-body">
  14 + <!-- 巡查记录卡片(统一卡片样式) -->
  15 + <view class="plan-card" v-for="(i, index) in orderDetail" :key="index">
  16 + <view class="plan-card__head">
  17 + <view class="plan-card__title">{{ i.planName || '--' }}</view>
  18 + </view>
  19 +
  20 + <view class="u-body-item u-flex">
  21 + <view class="u-body-item-title">计划编码:</view>
  22 + <view class="u-line-1 u-body-value">{{ i.planNo || '--' }}</view>
  23 + </view>
  24 +
  25 + <view class="u-body-item u-flex">
  26 + <view class="u-body-item-title">养护周期:</view>
  27 + <view class="u-line-1 u-body-value">{{ `${i.rate}${uni.$dict.getDictLabel('cycle_id_type', i.cycleId)}` }}</view>
  28 + </view>
  29 +
  30 + <view class="u-body-item u-flex">
  31 + <view class="u-body-item-title">计划有效期:</view>
  32 + <view class="u-line-1 u-body-value">{{ `${timeFormat(i.beginTime,'yyyy-mm-dd')} 至 ${timeFormat(i. endTime,'yyyy-mm-dd')}` }}</view>
  33 + </view>
  34 +
  35 + <view class="u-body-item u-flex">
  36 + <view class="u-body-item-title">巡查描述:</view>
  37 + <view class="u-line-1 u-body-value">{{ i.remark || '--' }}</view>
  38 + </view>
  39 +
  40 + <view class="u-body-item u-flex">
  41 + <view class="u-body-item-title">提交时间:</view>
  42 + <view class="u-line-1 u-body-value">{{ i.finishTime==null?'--':timeFormat(i.finishTime,'yyyy-mm-dd hh:MM:ss') }}</view>
  43 + </view>
  44 +
  45 + <view class="u-body-item u-flex">
  46 + <view class="u-body-item-title">提交人:</view>
  47 + <view class="u-line-1 u-body-value">{{ i.userName || '--' }}</view>
  48 + </view>
  49 +
  50 + <!-- 照片 -->
  51 + <view class="photo-block">
  52 + <view class="u-body-item-title">照片:</view>
  53 + <view class="cell-content-wrap">
  54 + <up-album
  55 + v-if="!!i.imgList?.length"
  56 + :urls="i.imgList || []"
  57 + singleSize="70"
  58 + :preview-full-image="true"
  59 + ></up-album>
  60 + <text v-else class="empty-text">暂无问题照片</text>
  61 + </view>
  62 + </view>
95 63 </view>
96 64 </view>
97 65 <view v-else>
... ... @@ -145,14 +113,58 @@ onLoad((options) =&gt; {
145 113 </script>
146 114  
147 115 <style scoped lang="scss">
148   -
149   -// 内容容器
150   -.content-wrap {
151   - background: #fff;
152   - width: 100%;
  116 +/* 统一卡片样式(与巡查计划明细一致) */
  117 +.page-container {
  118 + min-height: 100vh;
  119 + padding-bottom: 40rpx;
  120 + background-color: #F4F6FA;
153 121 box-sizing: border-box;
154   - margin-bottom: 30rpx;
155 122 }
156 123  
  124 +.page-body {
  125 + padding: 0 24rpx;
  126 +}
157 127  
  128 +/* 记录卡片:白底圆角 + 标题 */
  129 +.plan-card {
  130 + margin: 24rpx 0 0;
  131 + padding: 28rpx 28rpx 24rpx;
  132 + background-color: #ffffff;
  133 + border-radius: 16rpx;
  134 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  135 +}
  136 +.plan-card__head {
  137 + display: flex;
  138 + align-items: center;
  139 + justify-content: space-between;
  140 + margin-bottom: 20rpx;
  141 +}
  142 +.plan-card__title {
  143 + flex: 1;
  144 + min-width: 0;
  145 + font-size: 32rpx;
  146 + font-weight: 500;
  147 + color: #1F2937;
  148 + overflow: hidden;
  149 + white-space: nowrap;
  150 + text-overflow: ellipsis;
  151 +}
  152 +.plan-card .u-body-item {
  153 + margin-bottom: 12rpx;
  154 +}
  155 +
  156 +/* 照片区块 */
  157 +.photo-block {
  158 + margin-top: 16rpx;
  159 + padding-top: 16rpx;
  160 + border-top: 1rpx solid #E8EBF0;
  161 +}
  162 +
  163 +/* 空文本 */
  164 +.empty-text {
  165 + color: #9CA3AF;
  166 + font-size: 26rpx;
  167 + line-height: 80rpx;
  168 + display: block;
  169 +}
158 170 </style>
159 171 \ No newline at end of file
... ...
pages-sub/daily/patrol-manage/index.vue
... ... @@ -7,7 +7,7 @@
7 7 :list="tabList"
8 8 :is-scroll="false"
9 9 :activeStyle="{
10   - color: '#3c9cff',
  10 + color: '#2563EB',
11 11 fontWeight: 'bold',
12 12 transform: 'scale(1.05)'
13 13 }"
... ... @@ -29,7 +29,7 @@
29 29 @custom="handleSearch"
30 30 :clearabled="false"
31 31 maxlength="50"
32   - style="margin: 20rpx 20rpx 0"
  32 + style="margin: 16rpx 24rpx 0"
33 33 ></up-search>
34 34 </view>
35 35 </up-sticky>
... ... @@ -44,53 +44,51 @@
44 44 <empty-view/>
45 45 </template>
46 46 <!-- 计划卡片列表 -->
47   - <view class="common-card-list" style="padding-top: 94px;">
48   -
49   - <up-card
50   - :border="false"
51   - :foot-border-top="false"
52   - :head-border-bottom="false"
53   - v-for="(item,index) in planList"
54   - :key="`${item.batchNo}_${index}`"
55   - :show-head="false"
56   - >
57   - <template #body>
58   - <view class="card-body">
59   - <view class="common-custom-btn " style="--btn-top: 80px;" @click="gotoDetail(item)">
60   - 计划明细
61   - </view>
62   - <view class="u-body-item u-flex">
63   - <view class="u-body-item-title">道路名称:</view>
64   - <view class="u-line-1 u-body-value">{{ item.roadName || '-' }}</view>
65   - </view>
66   -
67   -
68   -
69   - <view class="u-body-item u-flex">
70   - <view class="u-body-item-title">所属街道:</view>
71   - <view class="u-line-1 u-body-value">{{ item.streetName }}
72   - </view>
73   - </view>
74   -
75   - <view class="u-body-item u-flex common-item-center common-justify-between">
76   - <view class="u-body-item-title">养护级别: {{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}</view>
77   -
78   - </view>
79   -
80   - <view class="u-body-item u-flex">
81   - <view class="u-body-item-title">计划类型:</view>
82   - <view class="u-line-1 u-body-value">{{uni.$dict.getDictLabel('inspection_maintain_type', item.planTypeId)}}</view>
83   - </view>
84   -
85   - <view class="u-body-item u-flex">
86   - <view class="u-body-item-title">计划时间:</view>
87   - <view class="u-line-1 u-body-value">{{ timeFormat(item.beginTime, 'yyyy-mm-dd') || '-' }} 至
88   - {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }}
89   - </view>
90   - </view>
  47 + <view class="common-card-list" style="padding-top: 108px;">
  48 +
  49 + <view class="plan-card" v-for="(item,index) in planList" :key="`${item.batchNo}_${index}`">
  50 + <!-- 卡片标题:道路名称 + 状态标签 -->
  51 + <view class="plan-card__head">
  52 + <view class="plan-card__title">{{ item.roadName || '-' }}</view>
  53 + <view class="status-tag"
  54 + :class="activeTab === '1' ? 'common-pending-tag' : (activeTab === '2' ? 'common-finish-tag' : 'common-invalid-tag')">
  55 + {{ activeTab === '1' ? '待完成' : (activeTab === '2' ? '已完成' : (activeTab === '3' ? '已失效' : '已终止')) }}
91 56 </view>
92   - </template>
93   - </up-card>
  57 + </view>
  58 +
  59 + <view class="u-body-item u-flex">
  60 + <view class="u-body-item-title">计划编码:</view>
  61 + <view class="u-line-1 u-body-value">{{ item.batchNo || '-' }}</view>
  62 + </view>
  63 +
  64 + <view class="u-body-item u-flex">
  65 + <view class="u-body-item-title">所属街道:</view>
  66 + <view class="u-line-1 u-body-value">{{ item.streetName }}
  67 + </view>
  68 + </view>
  69 +
  70 + <view class="u-body-item u-flex">
  71 + <view class="u-body-item-title">养护级别:</view>
  72 + <view class="u-line-1 u-body-value">{{uni.$dict.getDictLabel('conserve_level', item.levelId) || '-'}}</view>
  73 + </view>
  74 +
  75 + <view class="u-body-item u-flex">
  76 + <view class="u-body-item-title">计划类型:</view>
  77 + <view class="u-line-1 u-body-value">{{uni.$dict.getDictLabel('inspection_maintain_type', item.planTypeId)}}</view>
  78 + </view>
  79 +
  80 + <view class="u-body-item u-flex">
  81 + <view class="u-body-item-title">计划时间:</view>
  82 + <view class="u-line-1 u-body-value">{{ timeFormat(item.beginTime, 'yyyy-mm-dd') || '-' }} 至
  83 + {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }}
  84 + </view>
  85 + </view>
  86 +
  87 + <!-- 底部操作区(分隔线 + 右对齐按钮) -->
  88 + <view class="card-action-row">
  89 + <view class="mini-btn mini-btn--primary" @click="gotoDetail(item)">计划明细</view>
  90 + </view>
  91 + </view>
94 92 </view>
95 93  
96 94 </z-paging>
... ... @@ -182,9 +180,39 @@ onShow(() =&gt; {
182 180 }
183 181 .sticky-header {
184 182 background-color: #ffffff;
185   - padding-bottom: 10rpx;
  183 + padding-bottom: 24rpx;
  184 + border-bottom: 1rpx solid #E8EBF0;
186 185 .search-input {
187   - margin: 20rpx 20rpx 10rpx !important;
  186 + margin: 16rpx 24rpx 0 !important;
188 187 }
189 188 }
  189 +
  190 +/* 计划卡片:白底圆角 + 标题/状态 + 底部操作区(设计稿 .tcard) */
  191 +.plan-card {
  192 + margin: 0 24rpx 24rpx;
  193 + padding: 28rpx 28rpx 24rpx;
  194 + background-color: #ffffff;
  195 + border-radius: 16rpx;
  196 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  197 +}
  198 +.plan-card__head {
  199 + display: flex;
  200 + align-items: center;
  201 + justify-content: space-between;
  202 + margin-bottom: 20rpx;
  203 +}
  204 +.plan-card__title {
  205 + flex: 1;
  206 + min-width: 0;
  207 + margin-right: 16rpx;
  208 + font-size: 32rpx;
  209 + font-weight: 500;
  210 + color: #1F2937;
  211 + overflow: hidden;
  212 + white-space: nowrap;
  213 + text-overflow: ellipsis;
  214 +}
  215 +.plan-card .u-body-item {
  216 + margin-bottom: 12rpx;
  217 +}
190 218 </style>
191 219 \ No newline at end of file
... ...
pages-sub/daily/patrol-manage/pending-plan-detail.vue
1 1 <template>
2 2 <view class="page-container">
3 3  
4   - <view class="common-card-list" style=" ">
5   - <up-card
6   - :border="false"
7   - :foot-border-top="false"
8   - v-for="(item,index) in planInfo"
9   - :key="`${item.planNo}_${index}`"
10   - >
11   - <!-- 自定义标题区域 -->
12   - <template #head>
13   - <view class="card-header">
14   - <view class="common-card-title common-name">{{ item.planName || '无计划名称' }}
  4 + <view class="page-body">
  5 + <view class="plan-card-wrap" v-for="(item,index) in planInfo" :key="`${item.planNo}_${index}`">
  6 +
  7 + <!-- 计划名称 -->
  8 + <view class="form-card form-card--title">
  9 + <view class="card-title">{{ item.planName || '无计划名称' }}</view>
  10 + </view>
  11 +
  12 + <!-- 计划信息 -->
  13 + <view class="form-card">
  14 + <view class="sec-head">
  15 + <view class="sec-bar"></view>
  16 + <view class="sec-title">计划信息</view>
  17 + </view>
  18 +
  19 + <view class="u-body-item u-flex">
  20 + <view class="u-body-item-title">计划编码:</view>
  21 + <view class="u-line-1 u-body-value">{{ item.planNo || '-' }}</view>
  22 + </view>
  23 + <view class="u-body-item u-flex">
  24 + <view class="u-body-item-title">养护周期:</view>
  25 + <view class="u-line-1 u-body-value">{{ item.rate || '-' }}
  26 + {{ uni.$dict.getDictLabel('cycle_id_type', item.cycleId) }}
15 27 </view>
16   - <!-- 已失效标识 -->
17   - <view v-show="item.finishState == 3 " class="common-invalid-tag">已失效</view>
18   - <view v-show="item.finishState == 2 " class="common-finish-tag">已完成</view>
19 28 </view>
20   - </template>
21   -
22   - <template #body>
23   - <view class="card-body">
24   -
25   - <!-- <up-button-->
26   - <!-- v-if="item.finishState ==3"-->
27   - <!-- type="primary"-->
28   - <!-- size="mini"-->
29   - <!-- @click=""-->
30   - <!-- class="submit-record-btn"-->
31   - <!-- :disabled="true"-->
32   - <!-- >-->
33   - <!-- 补交记录-->
34   - <!-- </up-button>-->
35   -
36   - <!-- <up-button-->
37   - <!-- v-if="item.finishState !== 3 && item.planFinishNum > 0"-->
38   - <!-- type="primary"-->
39   - <!-- size="mini"-->
40   - <!-- @click="gotoFinishPlanDetail(item)"-->
41   - <!-- class="submit-record-btn"-->
42   - <!-- >-->
43   - <!-- 提交记录-->
44   - <!-- </up-button>-->
45   - <!-- </view>-->
46   - <view class="common-custom-btn disable" style="--btn-top: 120px;" v-if="item.finishState ==3">
47   - 补交记录
48   - </view>
49   - <view class="common-custom-btn " style="--btn-top: 120px;"
50   - v-if="item.finishState !== 3 && item.planFinishNum > 0" @click="gotoFinishPlanDetail(item)">
51   - 提交记录
52   - </view>
53   - <view class="u-body-item u-flex">
54   - <view class="u-body-item-title">计划编码:</view>
55   - <view class="u-line-1 u-body-value">{{ item.planNo || '-' }}</view>
56   - </view>
57   - <view class="u-body-item u-flex">
58   - <view class="u-body-item-title">养护周期:</view>
59   - <view class="u-line-1 u-body-value">{{ item.rate || '-' }}
60   - {{ uni.$dict.getDictLabel('cycle_id_type', item.cycleId) }}
61   - </view>
62   - </view>
63   -
64   - <view class="u-body-item u-flex common-item-center common-justify-between">
65   - <view class="u-body-item-title">计划完成次数: {{ item.planNum || 0 }}</view>
66   - <!-- <view class="">-->
67   - <!-- <up-button-->
68   - <!-- v-if="item.finishState ==3"-->
69   - <!-- type="primary"-->
70   - <!-- size="mini"-->
71   - <!-- @click=""-->
72   - <!-- class="submit-record-btn"-->
73   - <!-- :disabled="true"-->
74   - <!-- >-->
75   - <!-- 补交记录-->
76   - <!-- </up-button>-->
77   -
78   - <!-- <up-button-->
79   - <!-- v-if="item.finishState !== 3 && item.planFinishNum > 0"-->
80   - <!-- type="primary"-->
81   - <!-- size="mini"-->
82   - <!-- @click="gotoFinishPlanDetail(item)"-->
83   - <!-- class="submit-record-btn"-->
84   - <!-- >-->
85   - <!-- 提交记录-->
86   - <!-- </up-button>-->
87   - <!-- </view>-->
88   - </view>
89   -
90   - <view class="u-body-item u-flex">
91   - <view class="u-body-item-title">已完成次数:</view>
92   - <view class="u-line-1 u-body-value">{{ item.planFinishNum || 0 }}</view>
93   - </view>
94   -
95   - <view class="u-body-item u-flex">
96   - <view class="u-body-item-title">计划有效期:</view>
97   - <view class="u-line-1 u-body-value">{{ timeFormat(item.beginTime, 'yyyy-mm-dd') || '-' }} 至
98   - {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }}
99   - </view>
100   - </view>
  29 +
  30 + <view class="u-body-item u-flex">
  31 + <view class="u-body-item-title">计划完成次数:</view>
  32 + <view class="u-line-1 u-body-value">{{ item.planNum || 0 }}</view>
  33 + </view>
  34 +
  35 + <view class="u-body-item u-flex">
  36 + <view class="u-body-item-title">已完成次数:</view>
  37 + <view class="u-line-1 u-body-value">{{ item.planFinishNum || 0 }}</view>
  38 + </view>
  39 +
  40 + <view class="u-body-item u-flex">
  41 + <view class="u-body-item-title">计划有效期:</view>
  42 + <view class="u-line-1 u-body-value">{{ timeFormat(item.beginTime, 'yyyy-mm-dd') || '-' }} 至
  43 + {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }}
101 44 </view>
102   - </template>
103   - </up-card>
  45 + </view>
  46 +
  47 + <!-- 底部操作区(分隔线 + 右对齐按钮) -->
  48 + <view class="card-action-row" v-if="item.finishState == 3 || item.planFinishNum > 0">
  49 + <view class="mini-btn mini-btn--primary is-disabled" v-if="item.finishState == 3">
  50 + 补交记录
  51 + </view>
  52 + <view class="mini-btn mini-btn--primary" v-if="item.finishState !== 3 && item.planFinishNum > 0"
  53 + @click="gotoFinishPlanDetail(item)">
  54 + 提交记录
  55 + </view>
  56 + </view>
  57 + </view>
  58 + </view>
104 59 </view>
105 60  
106 61  
... ... @@ -110,7 +65,6 @@
110 65 type="primary"
111 66 size="default"
112 67 @click="addNewRecord"
113   - :style="{ width: '100%', height: '88rpx', fontSize: '32rpx', borderRadius: 0 }"
114 68 >
115 69 新增记录
116 70 </up-button>
... ... @@ -171,6 +125,90 @@ const addNewRecord = () =&gt; {
171 125 </script>
172 126  
173 127 <style scoped lang="scss">
  128 +/* 统一卡片样式(与工单/巡查表单页一致) */
  129 +.page-container {
  130 + min-height: 100vh;
  131 + padding-bottom: 200rpx;
  132 + background-color: #F4F6FA;
  133 + box-sizing: border-box;
  134 +}
  135 +
  136 +.page-body {
  137 + padding: 0 24rpx;
  138 +}
  139 +
  140 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  141 +.form-card {
  142 + margin-top: 24rpx;
  143 + padding: 8rpx 24rpx;
  144 + background-color: #ffffff;
  145 + border-radius: 16rpx;
  146 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  147 +}
  148 +
  149 +// 区块标题:蓝色竖条 + 标题文字
  150 +.sec-head {
  151 + display: flex;
  152 + align-items: center;
  153 + gap: 12rpx;
  154 + padding: 20rpx 0 8rpx;
  155 +}
  156 +
  157 +.sec-bar {
  158 + width: 6rpx;
  159 + height: 28rpx;
  160 + background-color: #2563EB;
  161 + border-radius: 3rpx;
  162 +}
  163 +
  164 +.sec-title {
  165 + font-size: 30rpx;
  166 + font-weight: 500;
  167 + color: #1F2937;
  168 +}
  169 +
  170 +/* 计划名称卡片 */
  171 +.form-card--title {
  172 + padding: 28rpx 24rpx;
  173 +}
  174 +.card-title {
  175 + font-size: 32rpx;
  176 + font-weight: 500;
  177 + color: #1F2937;
  178 + line-height: 1.4;
  179 +}
  180 +
  181 +/* 信息行 */
  182 +.form-card .u-body-item {
  183 + margin-bottom: 12rpx;
  184 +
  185 + &:last-of-type {
  186 + margin-bottom: 0;
  187 + }
  188 +}
174 189  
  190 +/* 禁用态按钮 */
  191 +.mini-btn.is-disabled {
  192 + background-color: #93B4F5 !important;
  193 + opacity: 0.7;
  194 +}
175 195  
  196 +/* 底部提交栏 */
  197 +.fixed-bottom-btn-wrap {
  198 + position: fixed;
  199 + left: 0;
  200 + right: 0;
  201 + bottom: 0;
  202 + z-index: 999;
  203 + padding: 16rpx 24rpx;
  204 + padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
  205 + background-color: #ffffff;
  206 + box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
  207 + box-sizing: border-box;
  208 +}
  209 +.fixed-bottom-btn-wrap :deep(.u-button) {
  210 + height: 88rpx !important;
  211 + border-radius: 16rpx !important;
  212 + font-size: 30rpx !important;
  213 +}
176 214 </style>
177 215 \ No newline at end of file
... ...
pages-sub/daily/quick-order/add-order.vue
1 1 <template>
2 2 <view class="page-container">
3 3 <!-- 核心:将所有 up-form-item 包裹在同一个 up-form 内 -->
4   - <view class="work-order-form-content commonPageLRpadding">
  4 + <view class="work-order-form-content">
5 5 <up-form
6 6 label-position="left"
7 7 :model="workOrderForm"
8 8 ref="workOrderFormRef"
9 9 labelWidth="160rpx"
10 10 >
11   -
12   - <up-form-item
13   - label="业务线"
14   - prop="busiLineCn"
15   - border-bottom
16   - required
17   - >
18   - <up-radio-group
19   - v-model="workOrderForm.busiLineCn"
20   - placement="row"
21   - @change="handleBusiLineChange"
  11 + <!-- 工单信息 -->
  12 + <view class="form-card">
  13 + <view class="sec-head">
  14 + <view class="sec-bar"></view>
  15 + <view class="sec-title">工单信息</view>
  16 + </view>
  17 +
  18 + <up-form-item
  19 + label="业务线"
  20 + prop="busiLineCn"
  21 + border-bottom
  22 + required
  23 + class="form-item"
  24 + >
  25 + <up-radio-group
  26 + v-model="workOrderForm.busiLineCn"
  27 + placement="row"
  28 + @change="handleBusiLineChange"
  29 + >
  30 + <up-radio
  31 + v-for="item in busiLineOptions"
  32 + :key="item.name"
  33 + :label="item.name"
  34 + :name="item.name"
  35 + ></up-radio>
  36 + </up-radio-group>
  37 +
  38 + </up-form-item>
  39 + <!-- 1. 工单位置(地图选择) -->
  40 + <up-form-item
  41 + label="工单位置"
  42 + prop="workLocation"
  43 + border-bottom
  44 + required
  45 + class="form-item"
  46 + @click="chooseWorkLocation(); hideKeyboard()"
  47 + >
  48 + <up-input
  49 + v-model="workOrderForm.workLocation"
  50 + border="none"
  51 + readonly
  52 + suffix-icon="map-fill"
  53 + placeholder="点击选择工单位置"
  54 + ></up-input>
  55 + </up-form-item>
  56 +
  57 + <!-- 2. 道路名称(下拉框:位置选择后才可点击) -->
  58 + <up-form-item
  59 + label="道路名称"
  60 + prop="roadName"
  61 + border-bottom
  62 + required
  63 + class="form-item"
  64 + @click="workOrderForm.workLocation ? (showRoadName = true, hideKeyboard()) : uni.showToast({title: '请先选择工单位置', icon: 'none'})"
  65 + >
  66 + <up-input
  67 + v-model="workOrderForm.roadName"
  68 + readonly
  69 + disabled-color="#ffffff"
  70 + placeholder="请先选择工单位置"
  71 + border="none"
  72 + ></up-input>
  73 + <template #right>
  74 + <up-icon name="arrow-right" size="16" ></up-icon>
  75 + </template>
  76 + </up-form-item>
  77 +
  78 + <!-- 3. 问题类型(下拉框) -->
  79 + <up-form-item
  80 + label="问题类型"
  81 + prop="orderName"
  82 + border-bottom
  83 + required
  84 + class="form-item"
  85 + @click="showOrderName = true; hideKeyboard()"
22 86 >
23   - <up-radio
24   - v-for="item in busiLineOptions"
25   - :key="item.name"
26   - :label="item.name"
27   - :name="item.name"
28   - ></up-radio>
29   - </up-radio-group>
30   -
31   - </up-form-item>
32   - <!-- 1. 工单位置(地图选择) -->
33   - <up-form-item
34   - label="工单位置"
35   - prop="workLocation"
36   - border-bottom
37   - required
38   - @click="chooseWorkLocation(); hideKeyboard()"
39   - >
40   - <up-input
41   - v-model="workOrderForm.workLocation"
42   - border="none"
43   - readonly
44   - suffix-icon="map-fill"
45   - placeholder="点击选择工单位置"
46   - ></up-input>
47   - </up-form-item>
48   -
49   - <!-- 2. 道路名称(下拉框:位置选择后才可点击) -->
50   - <up-form-item
51   - label="道路名称"
52   - prop="roadName"
53   - border-bottom
54   - required
55   - @click="workOrderForm.workLocation ? (showRoadName = true, hideKeyboard()) : uni.showToast({title: '请先选择工单位置', icon: 'none'})"
56   - >
57   - <up-input
58   - v-model="workOrderForm.roadName"
59   - readonly
60   - disabled-color="#ffffff"
61   - placeholder="请先选择工单位置"
62   - border="none"
63   - ></up-input>
64   - <template #right>
65   - <up-icon name="arrow-right" size="16" ></up-icon>
66   - </template>
67   - </up-form-item>
68   -
69   - <!-- 3. 问题类型(下拉框) -->
70   - <up-form-item
71   - label="问题类型"
72   - prop="orderName"
73   - border-bottom
74   - required
75   - @click="showOrderName = true; hideKeyboard()"
76   - >
77   - <up-input
78   - v-model="workOrderForm.orderName"
79   - disabled
80   - disabled-color="#ffffff"
81   - placeholder="请选择问题类型"
82   - border="none"
83   - ></up-input>
84   - <template #right>
85   - <up-icon name="arrow-right" size="16"></up-icon>
86   - </template>
87   - </up-form-item>
  87 + <up-input
  88 + v-model="workOrderForm.orderName"
  89 + disabled
  90 + disabled-color="#ffffff"
  91 + placeholder="请选择问题类型"
  92 + border="none"
  93 + ></up-input>
  94 + <template #right>
  95 + <up-icon name="arrow-right" size="16"></up-icon>
  96 + </template>
  97 + </up-form-item>
  98 + </view>
88 99  
89 100 <!-- 4. 情况描述(文本域) -->
90   - <up-form-item
91   - label="情况描述"
92   - prop="problemDesc"
93   - required
94   - >
95   - <up-textarea
96   - placeholder="请输入情况描述(最多200字)"
97   - v-model.trim="workOrderForm.problemDesc"
98   - count
99   - maxlength="200"
100   - rows="4"
101   - @blur="() => $refs.workOrderFormRef.validateField('problemDesc')"
102   - ></up-textarea>
103   - </up-form-item>
  101 + <view class="form-card form-card--field">
  102 + <view class="sec-head">
  103 + <view class="sec-bar"></view>
  104 + <view class="sec-title">情况描述</view>
  105 + </view>
  106 + <up-form-item
  107 + label="情况描述"
  108 + prop="problemDesc"
  109 + required
  110 + class="form-item"
  111 + >
  112 + <up-textarea
  113 + placeholder="请输入情况描述(最多200字)"
  114 + v-model.trim="workOrderForm.problemDesc"
  115 + count
  116 + maxlength="200"
  117 + rows="4"
  118 + @blur="() => $refs.workOrderFormRef.validateField('problemDesc')"
  119 + ></up-textarea>
  120 + </up-form-item>
  121 + </view>
104 122  
105 123 <!-- 问题照片 -->
106   - <up-form-item label="问题照片" prop="problemImgs" required>
107   - <up-upload
108   - :file-list="problemImgsList"
109   - @after-read="(event) => uploadImgs(event, 'problemImgsList')"
110   - @delete="(event) => deleteImg(event, 'problemImgsList')"
111   - multiple
112   - width="70"
113   - height="70"
114   - :max-count="3"
115   - upload-text="选择问题照片"
116   - ></up-upload>
117   - </up-form-item>
  124 + <view class="form-card form-card--field">
  125 + <view class="sec-head">
  126 + <view class="sec-bar"></view>
  127 + <view class="sec-title">问题照片</view>
  128 + </view>
  129 + <up-form-item label="问题照片" prop="problemImgs" required class="form-item">
  130 + <up-upload
  131 + :file-list="problemImgsList"
  132 + @after-read="(event) => uploadImgs(event, 'problemImgsList')"
  133 + @delete="(event) => deleteImg(event, 'problemImgsList')"
  134 + multiple
  135 + width="70"
  136 + height="70"
  137 + :max-count="3"
  138 + upload-text="选择问题照片"
  139 + ></up-upload>
  140 + <view class="upload-hint">最少 1 张 · 最多 3 张</view>
  141 + </up-form-item>
  142 + </view>
118 143  
119 144 <!-- 完成照片 -->
120   - <up-form-item label="完成照片" prop="completeImgs" required class="mt-20">
121   - <up-upload
122   - :file-list="completeImgsList"
123   - @after-read="(event) => uploadImgs(event, 'completeImgsList')"
124   - @delete="(event) => deleteImg(event, 'completeImgsList')"
125   - multiple
126   - width="70"
127   - height="70"
128   - :max-count="3"
129   - :sizeType="['compressed']"
130   - upload-text="选择完成照片"
131   - ></up-upload>
132   - </up-form-item>
  145 + <view class="form-card form-card--field">
  146 + <view class="sec-head">
  147 + <view class="sec-bar"></view>
  148 + <view class="sec-title">完成照片</view>
  149 + </view>
  150 + <up-form-item label="完成照片" prop="completeImgs" required class="form-item">
  151 + <up-upload
  152 + :file-list="completeImgsList"
  153 + @after-read="(event) => uploadImgs(event, 'completeImgsList')"
  154 + @delete="(event) => deleteImg(event, 'completeImgsList')"
  155 + multiple
  156 + width="70"
  157 + height="70"
  158 + :max-count="3"
  159 + :sizeType="['compressed']"
  160 + upload-text="选择完成照片"
  161 + ></up-upload>
  162 + <view class="upload-hint">最少 1 张 · 最多 3 张</view>
  163 + </up-form-item>
  164 + </view>
133 165  
134 166 <!-- 处理结果(不必填) -->
135   - <up-form-item label="处理结果" prop="handleResult" class="mt-20">
136   - <up-textarea
137   - placeholder="请输入处理结果描述(最多200字,选填)"
138   - v-model.trim="workOrderForm.handleResult"
139   - count
140   - maxlength="200"
141   - rows="4"
142   - @blur="() => $refs.workOrderFormRef.validateField('handleResult')"
143   - ></up-textarea>
144   - </up-form-item>
  167 + <view class="form-card form-card--field">
  168 + <view class="sec-head">
  169 + <view class="sec-bar"></view>
  170 + <view class="sec-title">处理结果</view>
  171 + </view>
  172 + <up-form-item label="处理结果" prop="handleResult" class="form-item">
  173 + <up-textarea
  174 + placeholder="请输入处理结果描述(最多200字,选填)"
  175 + v-model.trim="workOrderForm.handleResult"
  176 + count
  177 + maxlength="200"
  178 + rows="4"
  179 + @blur="() => $refs.workOrderFormRef.validateField('handleResult')"
  180 + ></up-textarea>
  181 + </up-form-item>
  182 + </view>
145 183  
146 184 </up-form>
147 185 </view>
... ... @@ -150,7 +188,7 @@
150 188 <up-button
151 189 type="primary"
152 190 size="large"
153   - text="提交工单"
  191 + text="提交"
154 192 @click="submitWorkOrder"
155 193 ></up-button>
156 194 </view>
... ... @@ -585,14 +623,118 @@ export default {
585 623 </script>
586 624  
587 625 <style lang="scss" scoped>
588   -// 全局页面样式
  626 +/* 统一卡片样式(与工单/巡查表单页一致) */
589 627 .page-container {
590 628 min-height: 100vh;
  629 + padding-bottom: 200rpx;
  630 + background-color: #F4F6FA;
  631 + box-sizing: border-box;
591 632 }
592 633  
593 634 // 工单表单内容容器
594 635 .work-order-form-content {
595   - background: #fff;
596   - margin-bottom: 100rpx;
  636 + padding: 0 24rpx;
  637 + background: transparent;
  638 +}
  639 +
  640 +.form-item {
  641 + margin-bottom: 20rpx;
  642 +}
  643 +
  644 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  645 +.form-card {
  646 + margin-top: 24rpx;
  647 + padding: 8rpx 24rpx;
  648 + background-color: #ffffff;
  649 + border-radius: 16rpx;
  650 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  651 +}
  652 +
  653 +// 区块标题:蓝色竖条 + 标题文字
  654 +.sec-head {
  655 + display: flex;
  656 + align-items: center;
  657 + gap: 12rpx;
  658 + padding: 20rpx 0 8rpx;
  659 +}
  660 +.sec-bar {
  661 + width: 6rpx;
  662 + height: 28rpx;
  663 + background-color: #2563EB;
  664 + border-radius: 3rpx;
  665 +}
  666 +.sec-title {
  667 + font-size: 30rpx;
  668 + font-weight: 500;
  669 + color: #1F2937;
  670 +}
  671 +
  672 +// 表单行:上下 24rpx(左右由卡片内边距控制)
  673 +.form-card .form-item {
  674 + margin-bottom: 0;
  675 +}
  676 +.form-card :deep(.u-form-item__body) {
  677 + padding: 24rpx 0 !important;
  678 +}
  679 +.form-card :deep(.u-form-item__body__left__content__label) {
  680 + font-size: 28rpx;
  681 + color: #333333;
  682 +}
  683 +.form-card :deep(.u-line) {
  684 + background-color: #EEF1F6;
  685 +}
  686 +/* 卡片内最后一行不画分隔线 */
  687 +.form-card :deep(.u-form-item:last-child .u-line) {
  688 + display: none;
  689 +}
  690 +
  691 +/* 情况描述 / 照片 / 处理结果:分区标题已说明字段,隐藏左侧标签、内容整行铺满 */
  692 +.form-card--field :deep(.u-form-item__body__left) {
  693 + display: none;
  694 +}
  695 +.form-card--field :deep(.u-form-item__body__right) {
  696 + flex: 1;
  697 +}
  698 +.form-card--field :deep(.u-form-item__body) {
  699 + padding: 16rpx 0 24rpx;
  700 +}
  701 +/* 文本域:浅灰圆角输入区 */
  702 +.form-card--field :deep(.u-textarea) {
  703 + padding: 20rpx 20rpx 4rpx;
  704 + background-color: #F5F7FA;
  705 + border-radius: 12rpx;
  706 +}
  707 +.form-card--field :deep(.u-textarea__count) {
  708 + color: #9CA3AF;
  709 +}
  710 +/* 上传:虚线框 */
  711 +.form-card--field :deep(.u-upload__button) {
  712 + background-color: #FAFBFC;
  713 + border: 1rpx dashed #C8D2E0;
  714 + border-radius: 12rpx;
  715 +}
  716 +.upload-hint {
  717 + margin-top: 16rpx;
  718 + font-size: 24rpx;
  719 + color: #9CA3AF;
  720 +}
  721 +
  722 +/* 底部提交栏 */
  723 +.fixed-bottom-btn-wrap {
  724 + position: fixed;
  725 + left: 0;
  726 + right: 0;
  727 + bottom: 0;
  728 + z-index: 999;
  729 + padding: 16rpx 24rpx;
  730 + padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
  731 + background-color: #ffffff;
  732 + box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
  733 + box-sizing: border-box;
  734 +}
  735 +.fixed-bottom-btn-wrap :deep(.u-button) {
  736 + height: 88rpx !important;
  737 + border-radius: 16rpx !important;
  738 + font-size: 30rpx !important;
597 739 }
598 740 </style>
599 741 \ No newline at end of file
... ...
pages-sub/daily/quick-order/index.vue
... ... @@ -43,64 +43,37 @@
43 43 <empty-view/>
44 44 </template>
45 45  
46   - <view class="common-card-list" style=" padding-top: 100rpx;">
47   - <up-card
48   - :border="false"
49   - :foot-border-top="false"
50   - v-for="(item,index) in orderList"
51   - :key="`${item.orderNo}_${index}`"
52   - :show-head="false"
53   - >
54   -
55   - <template #body>
56   - <view class="card-body">
57   - <view class="common-custom-btn " style="--btn-top: 64px;" @click="handleDetail(item)">
58   - 工单详情
59   - <!-- <up-button-->
60   - <!-- type="primary"-->
61   -
62   - <!-- @click="gotoDetail(item)"-->
63   - <!-- class="submit-record-btn"-->
64   - <!-- >-->
65   - <!-- 计划明细-->
66   - <!-- </up-button>-->
67   - </view>
68   - <view class="u-body-item u-flex">
69   - <view class="u-body-item-title">工单编号:</view>
70   - <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view>
71   - </view>
72   - <view class="u-body-item u-flex">
73   - <view class="u-body-item-title">工单位置:</view>
74   - <view class="u-line-1 u-body-value">{{ item.lonLatAddress || '-' }}</view>
75   - </view>
76   -
77   - <view class="u-body-item u-flex ">
78   - <view class="u-body-item-title">工单名称:</view>
79   - <view class="u-line-1 u-body-value"> {{ item.orderName || '未填写' }}</view>
80   - </view>
81   -
82   - <view class="u-body-item u-flex">
83   - <view class="u-body-item-title">情况描述:</view>
84   - <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view>
85   - </view>
86   -
87   - <view class="u-body-item u-flex common-item-center common-justify-between">
88   - <view class="u-body-item-title u-body-value">提交时间:{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
89   -<!-- <view class="">-->
90   -<!-- <up-button-->
91   -<!-- type="primary"-->
92   -<!-- size="mini"-->
93   -<!-- @click="handleDetail(item)"-->
94   -
95   -<!-- >-->
96   -<!-- 工单详情-->
97   -<!-- </up-button>-->
98   -<!-- </view>-->
99   -
100   - </view>
101   - </view>
102   - </template>
103   - </up-card>
  46 + <view class="common-card-list" style="padding-top: 136rpx;padding-bottom: 180rpx">
  47 + <view class="plan-card" v-for="(item,index) in orderList" :key="`${item.orderNo}_${index}`">
  48 + <view class="u-body-item u-flex">
  49 + <view class="u-body-item-title">工单编号:</view>
  50 + <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view>
  51 + </view>
  52 + <view class="u-body-item u-flex">
  53 + <view class="u-body-item-title">工单位置:</view>
  54 + <view class="u-line-1 u-body-value">{{ item.lonLatAddress || '-' }}</view>
  55 + </view>
  56 +
  57 + <view class="u-body-item u-flex">
  58 + <view class="u-body-item-title">工单名称:</view>
  59 + <view class="u-line-1 u-body-value"> {{ item.orderName || '未填写' }}</view>
  60 + </view>
  61 +
  62 + <view class="u-body-item u-flex">
  63 + <view class="u-body-item-title">情况描述:</view>
  64 + <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view>
  65 + </view>
  66 +
  67 + <view class="u-body-item u-flex">
  68 + <view class="u-body-item-title">提交时间:</view>
  69 + <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
  70 + </view>
  71 +
  72 + <!-- 底部操作区(分隔线 + 右对齐按钮) -->
  73 + <view class="card-action-row">
  74 + <view class="mini-btn mini-btn--primary" @click="handleDetail(item)">工单详情</view>
  75 + </view>
  76 + </view>
104 77 </view>
105 78 </z-paging>
106 79  
... ... @@ -174,11 +147,34 @@ const handleAddOrder = () =&gt; {
174 147 </script>
175 148  
176 149 <style scoped lang="scss">
  150 +
  151 +/* 页面底色:统一浅灰蓝(设计稿 --page-bg) */
  152 +.page-container {
  153 + min-height: 100vh;
  154 + background-color: #F4F6FA;
  155 + box-sizing: border-box;
  156 +}
  157 +/* 列表卡片:统一卡片样式(白底 / 16rpx 圆角 / 浅投影) */
  158 +.plan-card {
  159 + margin: 0 24rpx 24rpx;
  160 + padding: 28rpx 28rpx 24rpx;
  161 + background-color: #ffffff;
  162 + border-radius: 16rpx;
  163 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  164 +}
  165 +.plan-card .u-body-item {
  166 + margin-bottom: 12rpx;
  167 +
  168 + &:last-of-type {
  169 + margin-bottom: 0;
  170 + }
  171 +}
  172 +
177 173 // 顶部搜索栏
178 174 .search-header {
179 175 display: flex;
180 176 align-items: center;
181   - padding: 20rpx;
  177 + padding: 24rpx;
182 178 background-color: #fff;
183 179 box-sizing: border-box;
184 180  
... ...
pages-sub/daily/quick-order/order-detail.vue
... ... @@ -5,7 +5,7 @@
5 5 v-if="loading"
6 6 :loading="true"
7 7 title="加载中..."
8   - color="#3c9cff"
  8 + color="#2563EB"
9 9 ></up-loading-page>
10 10  
11 11 <!-- 内容容器 -->
... ... @@ -16,109 +16,87 @@
16 16 </view>
17 17  
18 18 <!-- 工单详情内容 -->
19   - <up-cell-group :border="false" inset v-else>
20   - <!-- 1. 工单编号 -->
21   - <up-cell
22   - title="工单编号"
23   - :value="orderDetail.orderNo || '--'"
24   -
25   - align="middle"
26   - ></up-cell>
27   -
28   - <!-- 2. 工单位置 -->
29   - <up-cell
30   - align="middle"
31   - >
32   - <template #title>
33   - <view style="min-width: 200rpx">工单道路</view>
34   - </template>
35   - <template #value>
36   - <view class="up-line-1 common-text-color" >{{orderDetail.roadName || '--'}}</view>
37   - </template>
38   -
39   -
40   - </up-cell>
41   -
42   -
43   - <up-cell
44   - align="middle"
45   - >
46   - <template #title>
47   - <view style="min-width: 200rpx">工单位置</view>
48   - </template>
49   - <template #value>
50   - <view class="up-line-1 common-text-color" >{{orderDetail.lonLatAddress || '--'}}</view>
51   - </template>
52   - lonLatAddress
53   -
54   - </up-cell>
55   -
56   - <!-- 3. 问题类型 -->
57   - <up-cell
58   - title="问题类型"
59   - :value="orderDetail.orderName || '--'"
60   - align="middle"
61   - ></up-cell>
62   -
63   - <!-- 4. 情况描述 -->
64   - <up-cell
65   - align="middle"
66   - >
67   - <template #title>
68   - <view style="min-width: 200rpx">情况描述</view>
69   - </template>
70   - <template #value>
71   - <view class="up-line-1 common-text-color" >{{orderDetail.remark || '--'}}</view>
72   - </template>
73   - </up-cell>
74   -
75   - <!-- 5. 问题照片 -->
76   - <up-cell title="问题照片" >
77   - <template #value>
78   - <view class="cell-content-wrap" >
  19 + <view class="page-body" v-else>
  20 + <!-- 工单名称 -->
  21 + <view class="form-card form-card--title">
  22 + <view class="card-title">{{ orderDetail.orderName || '无工单名称' }}</view>
  23 + </view>
  24 +
  25 + <!-- 工单信息 -->
  26 + <view class="form-card">
  27 + <view class="sec-head">
  28 + <view class="sec-bar"></view>
  29 + <view class="sec-title">工单信息</view>
  30 + </view>
79 31  
  32 + <view class="u-body-item u-flex">
  33 + <view class="u-body-item-title">工单编号:</view>
  34 + <view class="u-line-1 u-body-value">{{ orderDetail.orderNo || '--' }}</view>
  35 + </view>
  36 + <view class="u-body-item u-flex">
  37 + <view class="u-body-item-title">工单道路:</view>
  38 + <view class="u-line-1 u-body-value">{{ orderDetail.roadName || '--' }}</view>
  39 + </view>
  40 + <view class="u-body-item u-flex">
  41 + <view class="u-body-item-title">工单位置:</view>
  42 + <view class="u-line-1 u-body-value">{{ orderDetail.lonLatAddress || '--' }}</view>
  43 + </view>
  44 + <view class="u-body-item u-flex">
  45 + <view class="u-body-item-title">问题类型:</view>
  46 + <view class="u-line-1 u-body-value">{{ orderDetail.orderName || '--' }}</view>
  47 + </view>
  48 + </view>
  49 +
  50 + <!-- 情况描述 -->
  51 + <view class="form-card">
  52 + <view class="sec-head">
  53 + <view class="sec-bar"></view>
  54 + <view class="sec-title">情况描述</view>
  55 + </view>
  56 + <view class="desc-text">{{ orderDetail.remark || '--' }}</view>
  57 + </view>
  58 +
  59 + <!-- 问题照片 -->
  60 + <view class="form-card">
  61 + <view class="sec-head">
  62 + <view class="sec-bar"></view>
  63 + <view class="sec-title">问题照片</view>
  64 + </view>
  65 + <view class="cell-content-wrap">
80 66 <up-album
81   - :urls="orderDetail.problemsImgs "
  67 + :urls="orderDetail.problemsImgs"
82 68 singleSize="70"
83 69 multipleSize="70"
84 70 :preview-full-image="true"
85   -
86 71 ></up-album>
87   -<!-- <text v-else class="empty-text">暂无问题照片</text>-->
88 72 </view>
89   - </template>
90   - </up-cell>
  73 + </view>
91 74  
92   - <!-- 6. 完成照片 -->
93   - <up-cell title="完成照片">
94   - <template #value>
  75 + <!-- 完成照片 -->
  76 + <view class="form-card">
  77 + <view class="sec-head">
  78 + <view class="sec-bar"></view>
  79 + <view class="sec-title">完成照片</view>
  80 + </view>
95 81 <view class="cell-content-wrap">
96 82 <up-album
97   -
98 83 :urls="orderDetail.endImgs"
99 84 singleSize="70"
100 85 multipleSize="70"
101 86 :preview-full-image="true"
102   -
103 87 ></up-album>
104   -<!-- <text v-else class="empty-text">暂无完成照片</text>-->
105 88 </view>
106   - </template>
107   - </up-cell>
108   -
109   - <!-- 7. 处理结果 -->
110   - <up-cell
111   - align="middle"
112   - :border="false"
113   - >
114   - <template #title>
115   - <view style="min-width: 200rpx">处理结果</view>
116   - </template>
117   - <template #value>
118   - <view class="up-line-1 common-text-color" >{{orderDetail.handleResult || '--'}}</view>
119   - </template>
120   - </up-cell>
121   - </up-cell-group>
  89 + </view>
  90 +
  91 + <!-- 处理结果 -->
  92 + <view class="form-card">
  93 + <view class="sec-head">
  94 + <view class="sec-bar"></view>
  95 + <view class="sec-title">处理结果</view>
  96 + </view>
  97 + <view class="desc-text">{{ orderDetail.handleResult || '--' }}</view>
  98 + </view>
  99 + </view>
122 100 </view>
123 101 </view>
124 102 </template>
... ... @@ -176,20 +154,85 @@ onLoad((options) =&gt; {
176 154 </script>
177 155  
178 156 <style scoped lang="scss">
  157 +/* 统一卡片样式(与工单/巡查详情页一致) */
  158 +.page-container {
  159 + min-height: 100vh;
  160 + padding-bottom: 40rpx;
  161 + background-color: #F4F6FA;
  162 + box-sizing: border-box;
  163 +}
179 164  
180 165 // 内容容器
181 166 .content-wrap {
182   - background: #fff;
183 167 width: 100%;
184 168 box-sizing: border-box;
185 169 }
  170 +.page-body {
  171 + padding: 0 24rpx;
  172 +}
  173 +
  174 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  175 +.form-card {
  176 + margin-top: 24rpx;
  177 + padding: 8rpx 24rpx 24rpx;
  178 + background-color: #ffffff;
  179 + border-radius: 16rpx;
  180 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  181 +}
  182 +
  183 +// 区块标题:蓝色竖条 + 标题文字
  184 +.sec-head {
  185 + display: flex;
  186 + align-items: center;
  187 + gap: 12rpx;
  188 + padding: 20rpx 0 8rpx;
  189 +}
  190 +.sec-bar {
  191 + width: 6rpx;
  192 + height: 28rpx;
  193 + background-color: #2563EB;
  194 + border-radius: 3rpx;
  195 +}
  196 +.sec-title {
  197 + font-size: 30rpx;
  198 + font-weight: 500;
  199 + color: #1F2937;
  200 +}
  201 +
  202 +/* 工单名称卡片 */
  203 +.form-card--title {
  204 + padding: 28rpx 24rpx;
  205 +}
  206 +.card-title {
  207 + font-size: 32rpx;
  208 + font-weight: 500;
  209 + color: #1F2937;
  210 + line-height: 1.4;
  211 +}
  212 +
  213 +/* 信息行 */
  214 +.form-card .u-body-item {
  215 + margin-bottom: 12rpx;
  216 +
  217 + &:last-of-type {
  218 + margin-bottom: 0;
  219 + }
  220 +}
  221 +
  222 +/* 长文本(情况描述 / 处理结果) */
  223 +.desc-text {
  224 + padding-top: 12rpx;
  225 + font-size: 28rpx;
  226 + color: #1F2937;
  227 + line-height: 1.6;
  228 + word-break: break-all;
  229 +}
186 230  
187 231 .cell-content-wrap {
  232 + padding-top: 12rpx;
188 233 :deep(image) { // 小程序中图片标签是image,且需要穿透样式隔离
189 234 width: 70px !important;
190 235 height: 70px !important;
191 236 }
192 237 }
193   -
194   -
195 238 </style>
196 239 \ No newline at end of file
... ...
pages-sub/data/tree-archive/addInspect.vue
... ... @@ -295,7 +295,7 @@
295 295 <!-- 栽种年月:标题下方、单选上方,绑定表单字段 inspectForm.weight.plantingDate -->
296 296 <view class="date-select-row" @click="showDatePicker = true" :class="pageType === 'detail' ? 'disabled-row' : ''">
297 297 <text>{{ inspectForm.weight.plantingDate || '请选择栽种年月' }}</text>
298   - <u-icon name="arrow-right" color="#999" size="16"></u-icon>
  298 + <u-icon name="arrow-right" color="#909399" size="16"></u-icon>
299 299 </view>
300 300  
301 301 <u-radio-group
... ... @@ -401,7 +401,7 @@
401 401 </u-collapse>
402 402  
403 403 <view class="risk-result-wrap">
404   - <view style="padding-bottom: 10px;">风险评估结果</view>
  404 + <view class="risk-result-title">风险评估结果</view>
405 405 <view class="risk-item">
406 406 <text class="risk-label">常规安全风险得分:</text>
407 407 <text class="risk-value">{{ riskResult.normalScore }}</text>
... ... @@ -1045,58 +1045,106 @@ onUnload(() =&gt; {
1045 1045 <style scoped lang="scss">
1046 1046 .inspect-add-container {
1047 1047 min-height: 100vh;
1048   - background-color: #fff;
  1048 + padding: 0 24rpx;
  1049 + box-sizing: border-box;
  1050 + background-color: #F4F6FA;
1049 1051 }
1050 1052 .inspect-scroll {
1051 1053 height: calc(100vh - 120rpx);
1052 1054 }
  1055 +
  1056 +/* 折叠面板:每个部位一张白色卡片(设计稿 .card) */
  1057 +.inspect-scroll :deep(.u-collapse) {
  1058 + padding-top: 8rpx;
  1059 +}
  1060 +.inspect-scroll :deep(.u-collapse-item) {
  1061 + margin: 24rpx 0;
  1062 + border-radius: 16rpx;
  1063 + overflow: hidden;
  1064 + background-color: #ffffff;
  1065 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  1066 +}
  1067 +/* 去掉折叠面板自带的分隔线,卡片之间改用间距区分 */
  1068 +.inspect-scroll :deep(.u-collapse > .u-line),
  1069 +.inspect-scroll :deep(.u-collapse-item > .u-line) {
  1070 + display: none;
  1071 +}
  1072 +.inspect-scroll :deep(.u-cell) {
  1073 + background-color: #ffffff;
  1074 +}
  1075 +.inspect-scroll :deep(.u-cell__body) {
  1076 + padding: 24rpx !important;
  1077 +}
  1078 +/* 折叠标题走 slot 渲染,u-cell__title 内是原生 text,需要按容器收口 */
  1079 +.inspect-scroll :deep(.u-cell__title),
  1080 +.inspect-scroll :deep(.u-cell__title-text),
  1081 +.inspect-scroll :deep(.u-cell__title text) {
  1082 + font-size: 28rpx !important;
  1083 + font-weight: 500 !important;
  1084 + color: #1F2937 !important;
  1085 +}
  1086 +.inspect-scroll :deep(.u-collapse-item__content__text) {
  1087 + padding: 0 24rpx 16rpx;
  1088 +}
  1089 +
1053 1090 .question-wrap {
1054 1091 padding: 15rpx 0;
1055   - border-bottom: 1rpx solid #f0f0f0;
  1092 + border-bottom: 1rpx solid #E8EBF0;
1056 1093 &:last-child {
1057 1094 border-bottom: none;
1058 1095 }
1059 1096 }
1060 1097 .question-title {
1061   - font-size: 14px;
  1098 + font-size: 28rpx;
1062 1099 line-height: 1.5;
1063 1100 margin: 15rpx 0;
1064   - color: #333;
  1101 + color: #1F2937;
1065 1102 .required {
1066   - color: #ff0000;
  1103 + color: #DC2626;
1067 1104 margin-right: 5rpx;
1068 1105 }
1069 1106 }
  1107 +/* 风险评估结果:独立白色卡片(设计稿 .card) */
1070 1108 .risk-result-wrap {
1071   - padding: 15rpx 15px;
  1109 + margin: 24rpx 0;
  1110 + padding: 24rpx;
  1111 + border-radius: 16rpx;
  1112 + background-color: #ffffff;
  1113 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  1114 +}
  1115 +.risk-result-title {
  1116 + padding-bottom: 16rpx;
  1117 + font-size: 30rpx;
  1118 + font-weight: 500;
  1119 + color: #1F2937;
1072 1120 }
1073 1121 .risk-item {
1074 1122 display: flex;
1075 1123 align-items: center;
1076 1124 margin-bottom: 15rpx;
1077   - font-size: 14px;
  1125 + font-size: 26rpx;
1078 1126 .risk-label {
1079   - color: #666;
  1127 + color: #9CA3AF;
1080 1128 margin-right: 10rpx;
1081 1129 }
1082 1130 .risk-value {
1083   - color: #333;
  1131 + color: #1F2937;
1084 1132 font-weight: 500;
1085 1133 }
1086 1134 }
1087 1135 .emergency-wrap {}
1088 1136  
1089 1137 .risk-level-low {
1090   - color: #00b42a;
  1138 + color: #16A34A;
1091 1139 }
1092 1140 .risk-level-normal {
1093   - color: #1989fa;
  1141 + color: #2563EB;
1094 1142 }
1095 1143 .risk-level-warning {
1096   - color: #ff9500;
  1144 + color: #D97706;
1097 1145 }
1098 1146 .risk-level-danger {
1099   - color: #ff0000;
  1147 + color: #DC2626;
1100 1148 }
1101 1149  
1102 1150 // 只读状态置灰
... ... @@ -1109,9 +1157,9 @@ onUnload(() =&gt; {
1109 1157 .modal-risk-content {
1110 1158 padding: 10px 0;
1111 1159 .modal-row {
1112   - font-size: 14px;
  1160 + font-size: 26rpx;
1113 1161 line-height: 2;
1114   - color: #333;
  1162 + color: #4B5563;
1115 1163 }
1116 1164 }
1117 1165  
... ... @@ -1126,6 +1174,8 @@ onUnload(() =&gt; {
1126 1174 :deep(.u-radio__text) {
1127 1175 min-width: 220rpx; /* 根据需求自行调大/调小 */
1128 1176 display: inline-block;
  1177 + font-size: 26rpx;
  1178 + color: #4B5563;
1129 1179 }
1130 1180  
1131 1181 /* 单列单选组,增加上下间距,避免误触 */
... ... @@ -1137,15 +1187,16 @@ onUnload(() =&gt; {
1137 1187 display: flex;
1138 1188 justify-content: space-between;
1139 1189 align-items: center;
1140   - padding: 18rpx 12rpx;
1141   - border: 1rpx solid #eee;
1142   - border-radius: 8rpx;
1143   - font-size: 14px;
1144   - color: #333;
  1190 + padding: 18rpx 20rpx;
  1191 + border: 1rpx solid #E8EBF0;
  1192 + border-radius: 12rpx;
  1193 + font-size: 26rpx;
  1194 + color: #4B5563;
  1195 + background-color: #FAFBFC;
1145 1196 margin-bottom: 12rpx;
1146 1197 &.disabled-row {
1147   - background: #f5f5f5;
1148   - color: #999;
  1198 + background: #F4F6FA;
  1199 + color: #9CA3AF;
1149 1200 }
1150 1201 }
1151 1202  
... ...
pages-sub/data/tree-archive/addTree.vue
1 1 <template>
2 2 <view class="page-container">
3 3 <up-form :model="formData" ref="formRef" label-width="140rpx" border-bottom>
4   - <up-form-item label="名称" prop="treetype" required>
5   - <up-input v-model.trim="formData.treetype" placeholder="请输入名称" maxlength="30" border="none"/>
6   - </up-form-item>
7   -
8   - <!-- 树种类型 底部弹窗选择 -->
9   - <!-- <up-form-item label="树种类型" prop="treeSpeciesType" required arrow @click="openTreeSpeciesType">
10   - <up-input
11   - v-model="formData.treeSpeciesTypeName"
12   - placeholder="请选择树种类型"
13   - readonly
14   - border="none"
15   - bg-color="transparent"
16   - />
17   - </up-form-item> -->
18   -
19   - <view class="form-row-wrap">
20   - <up-row gutter="10">
21   - <up-col span="6">
22   - <up-form-item label="胸径" prop="dbh" required>
23   - <up-input v-model.trim="formData.dbh" placeholder="请输入" maxlength="10" border="none" input-align="left"/>
24   - <template #right>
25   - <text style="padding-left: 12rpx;color:#ccc;font-size:14px">厘米</text>
26   - </template>
27   - </up-form-item>
28   - </up-col>
29   - <up-col span="6">
30   - <up-form-item label="高度" prop="treeheight">
31   - <up-input v-model.trim="formData.treeheight" placeholder="请输入" maxlength="10" border="none"
32   - input-align="left"/>
33   - <template #right>
34   - <text style="padding-left: 12rpx;color:#ccc;font-size:14px;">米</text>
35   - </template>
36   - </up-form-item>
37   - </up-col>
38   - </up-row>
39   - </view>
40   -
41   - <up-form-item label="位置" prop="growlocation" required class="location-form-item" @click="openMap">
42   - <up-input v-model="formData.growlocation" placeholder="请选择" readonly border="none"/>
43   - <template #right>
44   - <up-icon name="map" size="22"></up-icon>
45   - </template>
46   - </up-form-item>
47   -
48   - <up-row gutter="10">
49   - <up-col span="6">
50   - <up-form-item label="经度" :borderBottom="false">
51   - <up-input v-model="formData.longitude" placeholder="" readonly border="none"/>
52   - </up-form-item>
53   - </up-col>
54   - <up-col span="6">
55   - <up-form-item label="纬度" :borderBottom="false">
56   - <up-input v-model="formData.latitude" placeholder="" readonly border="none"/>
57   - </up-form-item>
58   - </up-col>
59   - </up-row>
60   -
61   - <up-form-item label="管护单位" prop="managedutyunit" required>
62   - <up-input v-model.trim="formData.managedutyunit" placeholder="请输入" maxlength="30" border="none"/>
63   - </up-form-item>
64   -
65   - <up-form-item label="权属分类" prop="oldtreeownershipText" required arrow @click="handleActionSheetOpen('ownership')">
66   - <up-input v-model.trim="formData.oldtreeownershipText" placeholder="请选择" readonly border="none"
67   - bg-color="transparent"/>
68   - </up-form-item>
69   -
70   - <up-form-item label="图片信息" prop="treeImgList" required>
71   - <up-upload
72   - :file-list="treeImgs.imgList.value || []"
73   - @after-read="treeImgs.uploadImgs"
74   - @delete="treeImgs.deleteImg"
75   - multiple
76   - :width="70"
77   - :height="70"
78   - :max-count="treeImgs.uploadConfig.maxCount"
79   - :upload-text="treeImgs.uploadText"
80   - :size-type="treeImgs.uploadConfig.sizeType"
81   - ></up-upload>
82   - </up-form-item>
  4 + <!-- 基础信息卡片(设计稿 .card.pad + .fgrp-title) -->
  5 + <view class="form-card">
  6 + <view class="sec-head">
  7 + <view class="sec-bar"></view>
  8 + <text class="sec-title">基础信息</text>
  9 + </view>
83 10  
84   - <view
85   - class="animated-area"
86   - :style="{
87   - height: isShow ? contentHeight + 'px' : '0',
88   - opacity: isShow ? 1 : 0,
89   - overflow: 'hidden'
90   - }"
91   - >
92   - <up-row gutter="10">
93   - <up-col span="6">
94   - <up-form-item label="拉丁文" prop="latinname">
95   - <up-input v-model.trim="formData.latinname" placeholder="请输入" maxlength="30" border="none"/>
96   - </up-form-item>
97   - </up-col>
98   - <up-col span="6">
99   - <up-form-item label="级别" arrow @click="handleActionSheetOpen('level')">
100   - <up-input v-model.trim="formData.treeleveltext" placeholder="请选择" readonly border="none"
101   - bg-color="transparent"/>
102   - </up-form-item>
103   - </up-col>
104   - </up-row>
105   -
106   - <up-form-item label="生长环境" prop="growthenvironment">
107   - <up-input v-model.trim="formData.growthenvironment" placeholder="请输入" maxlength="50" border="none"/>
  11 + <up-form-item label="名称" prop="treetype" required>
  12 + <up-input v-model.trim="formData.treetype" placeholder="请输入名称" maxlength="30" border="none"/>
108 13 </up-form-item>
109 14  
  15 + <!-- 树种类型 底部弹窗选择 -->
  16 + <!-- <up-form-item label="树种类型" prop="treeSpeciesType" required arrow @click="openTreeSpeciesType">
  17 + <up-input
  18 + v-model="formData.treeSpeciesTypeName"
  19 + placeholder="请选择树种类型"
  20 + readonly
  21 + border="none"
  22 + bg-color="transparent"
  23 + />
  24 + </up-form-item> -->
  25 +
110 26 <view class="form-row-wrap">
111 27 <up-row gutter="10">
112 28 <up-col span="6">
113   - <!-- 栽种年月 年月选择器 -->
114   - <up-form-item label="栽种年月" arrow @click="openPlantDatePicker">
115   - <up-input v-model.trim="formData.plantingDate" placeholder="请选择栽种年月" readonly border="none" bg-color="transparent"/>
  29 + <up-form-item label="胸径" prop="dbh" required>
  30 + <up-input v-model.trim="formData.dbh" placeholder="请输入" maxlength="10" border="none" input-align="left"/>
  31 + <template #right>
  32 + <text style="padding-left: 12rpx;color:#9CA3AF;font-size:26rpx">厘米</text>
  33 + </template>
116 34 </up-form-item>
117 35 </up-col>
118 36 <up-col span="6">
119   - <up-form-item label="干周" prop="weekday">
120   - <up-input v-model.trim="formData.weekday" placeholder="请输入" maxlength="10" border="none"
  37 + <up-form-item label="高度" prop="treeheight">
  38 + <up-input v-model.trim="formData.treeheight" placeholder="请输入" maxlength="10" border="none"
121 39 input-align="left"/>
122 40 <template #right>
123   - <text style="padding-left:12rpx;color:#ccc;font-size:14px">厘米</text>
  41 + <text style="padding-left: 12rpx;color:#9CA3AF;font-size:26rpx;">米</text>
124 42 </template>
125 43 </up-form-item>
126 44 </up-col>
127 45 </up-row>
128 46 </view>
129 47  
130   - <view class="form-row-wrap">
  48 + <up-form-item label="位置" prop="growlocation" required class="location-form-item" @click="openMap">
  49 + <up-input v-model="formData.growlocation" placeholder="请选择" readonly border="none"/>
  50 + <template #right>
  51 + <view class="loc-select">
  52 + <up-icon name="map" size="15" color="#2563EB"></up-icon>
  53 + <text class="loc-select-text">定位</text>
  54 + </view>
  55 + </template>
  56 + </up-form-item>
  57 +
  58 + <!-- 经纬度:只读展示,定位成功后自动回填(设计稿 .ta 灰底信息块) -->
  59 + <view class="coord-row">
  60 + <view class="coord">
  61 + <text class="coord-k">经度</text>
  62 + <text class="coord-v">{{ formData.longitude || '定位后自动填充' }}</text>
  63 + </view>
  64 + <view class="coord-line"></view>
  65 + <view class="coord">
  66 + <text class="coord-k">纬度</text>
  67 + <text class="coord-v">{{ formData.latitude || '定位后自动填充' }}</text>
  68 + </view>
  69 + </view>
  70 +
  71 + <up-form-item label="管护单位" prop="managedutyunit" required>
  72 + <up-input v-model.trim="formData.managedutyunit" placeholder="请输入" maxlength="30" border="none"/>
  73 + </up-form-item>
  74 +
  75 + <up-form-item label="权属分类" prop="oldtreeownershipText" required @click="handleActionSheetOpen('ownership')">
  76 + <up-input v-model.trim="formData.oldtreeownershipText" placeholder="请选择" readonly border="none"
  77 + input-align="right" bg-color="transparent"/>
  78 + <template #right>
  79 + <up-icon name="arrow-right" size="12" color="#C0C6D0"></up-icon>
  80 + </template>
  81 + </up-form-item>
  82 + </view>
  83 +
  84 + <!-- 树木照片卡片 -->
  85 + <view class="form-card">
  86 + <view class="sec-head">
  87 + <view class="sec-bar"></view>
  88 + <text class="sec-title">树木照片</text>
  89 + </view>
  90 + <up-form-item label="图片信息" prop="treeImgList" required :border-bottom="false">
  91 + <view class="upload-row">
  92 + <up-upload
  93 + :file-list="treeImgs.imgList.value || []"
  94 + @after-read="treeImgs.uploadImgs"
  95 + @delete="treeImgs.deleteImg"
  96 + multiple
  97 + :width="70"
  98 + :height="70"
  99 + :max-count="treeImgs.uploadConfig.maxCount"
  100 + :upload-text="treeImgs.uploadText"
  101 + :size-type="treeImgs.uploadConfig.sizeType"
  102 + ></up-upload>
  103 + <view class="upload-tip">
  104 + <text class="upload-tip-line">最少 1 张,最多 {{ treeImgs.uploadConfig.maxCount }} 张</text>
  105 + <text class="upload-tip-line">支持 jpg / png 格式</text>
  106 + </view>
  107 + </view>
  108 + </up-form-item>
  109 + </view>
  110 +
  111 + <view
  112 + class="animated-area"
  113 + :style="{
  114 + height: isShow ? 'auto' : '0',
  115 + opacity: isShow ? 1 : 0,
  116 + overflow: 'hidden'
  117 + }"
  118 + >
  119 + <view class="form-card">
  120 + <view class="sec-head">
  121 + <view class="sec-bar"></view>
  122 + <text class="sec-title">扩展信息</text>
  123 + </view>
  124 +
131 125 <up-row gutter="10">
132 126 <up-col span="6">
133   - <up-form-item label="东西冠幅" prop="canopyeastwest">
134   - <up-input v-model.trim="formData.canopyeastwest" placeholder="请输入" maxlength="10" border="none"
135   - input-align="left"/>
136   - <template #right>
137   - <text style="padding-left:12rpx;color:#ccc;font-size:14px">米</text>
138   - </template>
  127 + <up-form-item label="拉丁文" prop="latinname">
  128 + <up-input v-model.trim="formData.latinname" placeholder="请输入" maxlength="30" border="none"/>
139 129 </up-form-item>
140 130 </up-col>
141 131 <up-col span="6">
142   - <up-form-item label="南北冠幅" prop="canopysouthnorth">
143   - <up-input v-model.trim="formData.canopysouthnorth" placeholder="请输入" maxlength="10" border="none"
144   - input-align="left"/>
  132 + <up-form-item label="级别" @click="handleActionSheetOpen('level')">
  133 + <up-input v-model.trim="formData.treeleveltext" placeholder="请选择" readonly border="none"
  134 + input-align="right" bg-color="transparent"/>
145 135 <template #right>
146   - <text style="padding-left:12rpx;color:#ccc;font-size:14px">米</text>
  136 + <up-icon name="arrow-right" size="12" color="#C0C6D0"></up-icon>
147 137 </template>
148 138 </up-form-item>
149 139 </up-col>
150 140 </up-row>
  141 +
  142 + <up-form-item label="生长环境" prop="growthenvironment">
  143 + <up-input v-model.trim="formData.growthenvironment" placeholder="请输入" maxlength="50" border="none"/>
  144 + </up-form-item>
  145 +
  146 + <view class="form-row-wrap">
  147 + <up-row gutter="10">
  148 + <up-col span="6">
  149 + <!-- 栽种年月 年月选择器 -->
  150 + <up-form-item label="栽种年月" @click="openPlantDatePicker">
  151 + <up-input v-model.trim="formData.plantingDate" placeholder="请选择栽种年月" readonly border="none"
  152 + input-align="right" bg-color="transparent"/>
  153 + </up-form-item>
  154 + </up-col>
  155 + <up-col span="6">
  156 + <up-form-item label="干周" prop="weekday">
  157 + <up-input v-model.trim="formData.weekday" placeholder="请输入" maxlength="10" border="none"
  158 + input-align="left"/>
  159 + <template #right>
  160 + <text style="padding-left:12rpx;color:#9CA3AF;font-size:26rpx">厘米</text>
  161 + </template>
  162 + </up-form-item>
  163 + </up-col>
  164 + </up-row>
  165 + </view>
  166 +
  167 + <view class="form-row-wrap">
  168 + <up-row gutter="10">
  169 + <up-col span="6">
  170 + <up-form-item label="东西冠幅" prop="canopyeastwest">
  171 + <up-input v-model.trim="formData.canopyeastwest" placeholder="请输入" maxlength="10" border="none"
  172 + input-align="left"/>
  173 + <template #right>
  174 + <text style="padding-left:12rpx;color:#9CA3AF;font-size:26rpx">米</text>
  175 + </template>
  176 + </up-form-item>
  177 + </up-col>
  178 + <up-col span="6">
  179 + <up-form-item label="南北冠幅" prop="canopysouthnorth">
  180 + <up-input v-model.trim="formData.canopysouthnorth" placeholder="请输入" maxlength="10" border="none"
  181 + input-align="left"/>
  182 + <template #right>
  183 + <text style="padding-left:12rpx;color:#9CA3AF;font-size:26rpx">米</text>
  184 + </template>
  185 + </up-form-item>
  186 + </up-col>
  187 + </up-row>
  188 + </view>
151 189 </view>
152 190 </view>
153 191  
154   - <up-button
155   - @click="toggleArea"
156   - type="primary"
157   - plain
158   - size="large"
159   - style="margin-top:20rpx"
160   - >
161   - {{ isShow ? '- 隐藏区域' : '+ 显示区域' }}
162   - </up-button>
  192 + <!-- 展开/收起扩展信息 -->
  193 + <view class="expand-bar" @click="toggleArea">
  194 + <up-icon :name="isShow ? 'arrow-up' : 'arrow-down'" size="12" color="#2563EB"></up-icon>
  195 + <text class="expand-text">{{ isShow ? '收起更多信息' : '展开更多信息' }}</text>
  196 + </view>
163 197 </up-form>
164 198  
165 199 <view style="height: 60px;width: 100%"></view>
... ... @@ -513,10 +547,172 @@ const submit = async () =&gt; {
513 547 </script>
514 548  
515 549 <style scoped lang="scss">
  550 +/* 页面底色 + 留白(设计稿 --page-bg / .body) */
516 551 .page-container {
517   - padding: 15px;
  552 + padding: 24rpx;
  553 + padding-bottom: 200rpx; // 给底部固定按钮留空间
518 554 box-sizing: border-box;
519   - background: #fff;
  555 + background-color: #F4F6FA;
  556 +}
  557 +
  558 +/* 表单本身不铺底色,白卡片交给下面的 .form-card 分组(设计稿 .card.pad) */
  559 +.page-container :deep(.u-form) {
  560 + padding: 0;
  561 + background-color: transparent;
  562 +}
  563 +.page-container :deep(.u-line) {
  564 + background-color: #EEF1F6;
  565 +}
  566 +
  567 +/* 分组卡片:白底 16rpx 圆角 + 浅投影,卡片之间 24rpx */
  568 +.form-card {
  569 + padding: 8rpx 24rpx 16rpx;
  570 + background-color: #ffffff;
  571 + border-radius: 16rpx;
  572 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  573 +}
  574 +.form-card + .form-card,
  575 +.animated-area > .form-card {
  576 + margin-top: 24rpx;
  577 +}
  578 +/* 卡片内最后一行不画分隔线 */
  579 +.page-container :deep(.u-form-item:last-child .u-line) {
  580 + display: none;
  581 +}
  582 +
  583 +/* 分区标题:蓝色竖条 + 标题文字 */
  584 +.sec-head {
  585 + display: flex;
  586 + align-items: center;
  587 + gap: 12rpx;
  588 + padding: 20rpx 0 8rpx;
  589 +}
  590 +.sec-bar {
  591 + width: 6rpx;
  592 + height: 28rpx;
  593 + background-color: #2563EB;
  594 + border-radius: 3rpx;
  595 +}
  596 +.sec-title {
  597 + font-size: 30rpx;
  598 + font-weight: 500;
  599 + color: #1F2937;
  600 +}
  601 +
  602 +/* 表单行:标签 28rpx 深色,输入值 26rpx 内容色 */
  603 +.page-container :deep(.u-form-item__body) {
  604 + padding: 24rpx 0 !important;
  605 +}
  606 +.page-container :deep(.u-form-item__body__left__content__label) {
  607 + font-size: 28rpx;
  608 + color: #1F2937;
  609 +}
  610 +.page-container :deep(.u-input__inner) {
  611 + font-size: 26rpx;
  612 + color: #1F2937;
  613 +}
  614 +/* 必填星号统一用超时红(设计稿 .frow .req) */
  615 +.page-container :deep(.u-form-item__body__left__content__required) {
  616 + color: #DC2626 !important;
  617 +}
  618 +
  619 +/* 位置行右侧「定位」入口 */
  620 +.loc-select {
  621 + display: flex;
  622 + align-items: center;
  623 + gap: 6rpx;
  624 +}
  625 +.loc-select-text {
  626 + font-size: 24rpx;
  627 + color: #2563EB;
  628 +}
  629 +
  630 +/* 经纬度信息条:灰底圆角块,只读展示(设计稿 .ta) */
  631 +.coord-row {
  632 + display: flex;
  633 + align-items: center;
  634 + margin: 8rpx 0 16rpx;
  635 + padding: 16rpx 20rpx;
  636 + background-color: #F4F6FA;
  637 + border-radius: 12rpx;
  638 +}
  639 +.coord {
  640 + flex: 1;
  641 + min-width: 0;
  642 + display: flex;
  643 + align-items: center;
  644 + gap: 8rpx;
  645 +}
  646 +.coord-k {
  647 + flex-shrink: 0;
  648 + font-size: 22rpx;
  649 + color: #9CA3AF;
  650 +}
  651 +.coord-v {
  652 + flex: 1;
  653 + min-width: 0;
  654 + font-size: 24rpx;
  655 + color: #4B5563;
  656 + overflow: hidden;
  657 + text-overflow: ellipsis;
  658 + white-space: nowrap;
  659 +}
  660 +.coord-line {
  661 + flex-shrink: 0;
  662 + width: 1rpx;
  663 + height: 24rpx;
  664 + margin: 0 20rpx;
  665 + background-color: #E8EBF0;
  666 +}
  667 +
  668 +/* 图片上传:虚线框 + 右侧说明文案(设计稿 .uploader / .up-tip) */
  669 +.upload-row {
  670 + display: flex;
  671 + align-items: flex-start;
  672 + gap: 16rpx;
  673 +}
  674 +.page-container :deep(.u-upload__button) {
  675 + background-color: #F8FAFC !important;
  676 + border: 2rpx dashed #D5DAE2 !important;
  677 + border-radius: 12rpx !important;
  678 + box-sizing: border-box;
  679 +}
  680 +.page-container :deep(.u-upload__button__text) {
  681 + font-size: 22rpx !important;
  682 + color: #9CA3AF !important;
  683 +}
  684 +.page-container :deep(.u-upload__wrap__preview) {
  685 + border-radius: 12rpx !important;
  686 + overflow: hidden;
  687 +}
  688 +.upload-tip {
  689 + flex: 1;
  690 + min-width: 0;
  691 + display: flex;
  692 + flex-direction: column;
  693 + gap: 6rpx;
  694 + padding-top: 8rpx;
  695 +}
  696 +.upload-tip-line {
  697 + font-size: 22rpx;
  698 + line-height: 1.5;
  699 + color: #9CA3AF;
  700 +}
  701 +
  702 +/* 展开/收起:浅蓝底整行按钮(设计稿 .btn.soft) */
  703 +.expand-bar {
  704 + display: flex;
  705 + align-items: center;
  706 + justify-content: center;
  707 + gap: 8rpx;
  708 + height: 80rpx;
  709 + margin-top: 24rpx;
  710 + background-color: #EBF3FF;
  711 + border-radius: 12rpx;
  712 +}
  713 +.expand-text {
  714 + font-size: 26rpx;
  715 + color: #2563EB;
520 716 }
521 717  
522 718 .animated-area {
... ... @@ -541,7 +737,7 @@ const submit = async () =&gt; {
541 737 left: 0;
542 738 bottom: -20rpx;
543 739 line-height: 20rpx;
544   - font-size: 22rpx;
  740 + font-size: 24rpx;
545 741 color: #f56c6c;
546 742 width: 100%;
547 743 box-sizing: border-box;
... ...
pages-sub/data/tree-archive/editTree.vue
... ... @@ -6,8 +6,8 @@
6 6 <up-tabs
7 7 v-model="activeTab"
8 8 :list="tabList"
9   - active-color="#1989fa"
10   - inactive-color="#666"
  9 + active-color="#2563EB"
  10 + inactive-color="#606266"
11 11 font-size="30rpx"
12 12 @click="handleTabChange"
13 13 :scrollable="false"
... ... @@ -17,6 +17,11 @@
17 17  
18 18 <!-- Tab0 基本信息页面 -->
19 19 <view v-show="activeTab === 0" class="base-info-wrap">
  20 + <!-- 分区标题:蓝色竖条 + 标题文字(设计稿 .fgrp-title) -->
  21 + <view class="sec-head">
  22 + <view class="sec-bar"></view>
  23 + <text class="sec-title">基础信息</text>
  24 + </view>
20 25 <up-form :model="formData" ref="formRef" label-width="140rpx" border-bottom>
21 26 <up-form-item label="名称" prop="treetype" required>
22 27 <up-input v-model.trim="formData.treetype" placeholder="请输入名称" maxlength="30" border="none"/>
... ... @@ -40,7 +45,7 @@
40 45 <up-input v-model.trim="formData.dbh" placeholder="请输入" maxlength="10" border="none"
41 46 input-align="left"/>
42 47 <template #right>
43   - <text style="padding-left: 12rpx;color:#ccc;font-size:14px">厘米</text>
  48 + <text style="padding-left: 12rpx;color:#9CA3AF;font-size:26rpx">厘米</text>
44 49 </template>
45 50 </up-form-item>
46 51 </up-col>
... ... @@ -49,7 +54,7 @@
49 54 <up-input v-model.trim="formData.treeheight" placeholder="请输入" maxlength="10" border="none"
50 55 input-align="left"/>
51 56 <template #right>
52   - <text style="padding-left: 12rpx;color:#ccc;font-size:14px;">米</text>
  57 + <text style="padding-left: 12rpx;color:#9CA3AF;font-size:26rpx;">米</text>
53 58 </template>
54 59 </up-form-item>
55 60 </up-col>
... ... @@ -140,7 +145,7 @@
140 145 <up-input v-model.trim="formData.weekday" placeholder="请输入" maxlength="10" border="none"
141 146 input-align="left"/>
142 147 <template #right>
143   - <text style="padding-left:12rpx;color:#ccc;font-size:14px">厘米</text>
  148 + <text style="padding-left:12rpx;color:#9CA3AF;font-size:26rpx">厘米</text>
144 149 </template>
145 150 </up-form-item>
146 151 </up-col>
... ... @@ -154,7 +159,7 @@
154 159 <up-input v-model.trim="formData.canopyeastwest" placeholder="请输入" maxlength="10" border="none"
155 160 input-align="left"/>
156 161 <template #right>
157   - <text style="padding-left:12rpx;color:#ccc;font-size:14px">米</text>
  162 + <text style="padding-left:12rpx;color:#9CA3AF;font-size:26rpx">米</text>
158 163 </template>
159 164 </up-form-item>
160 165 </up-col>
... ... @@ -163,7 +168,7 @@
163 168 <up-input v-model.trim="formData.canopysouthnorth" placeholder="请输入" maxlength="10" border="none"
164 169 input-align="left"/>
165 170 <template #right>
166   - <text style="padding-left:12rpx;color:#ccc;font-size:14px">米</text>
  171 + <text style="padding-left:12rpx;color:#9CA3AF;font-size:26rpx">米</text>
167 172 </template>
168 173 </up-form-item>
169 174 </up-col>
... ... @@ -232,11 +237,11 @@
232 237 <view style="text-align: right">{{ timeFormat(item.updatetime) }}</view>
233 238 </view>
234 239 <view class=" fs-align__center" style="margin: 8px 0">
235   - <img src="../../../static/imgs/tree/tree-high.png" style="width:12px;height:12px;margin-right:6px;"
  240 + <img src="../../../static/imgs/tree/tree-high.png" style="width:24rpx;height:24rpx;margin-right:8rpx;"
236 241 alt=""> 高度:{{ item.treeheight }} 米
237 242 </view>
238 243 <view class=" fs-align__center">
239   - <img src="../../../static/imgs/tree/treearound.png" style="width:12px;height:12px;margin-right:6px;"
  244 + <img src="../../../static/imgs/tree/treearound.png" style="width:24rpx;height:24rpx;margin-right:8rpx;"
240 245 alt="">胸径:{{ item.dbh }} 厘米
241 246 </view>
242 247 </view>
... ... @@ -700,18 +705,68 @@ const toAddInspect = () =&gt; {
700 705 <style scoped lang="scss">
701 706 .container {
702 707 min-height: 100vh;
703   - padding-bottom: 100rpx;
  708 + padding-bottom: 200rpx;
  709 + background-color: #F4F6FA;
  710 + box-sizing: border-box;
704 711 }
705 712  
706 713 .header-wrap {
707   - background-color: #fff;
  714 + background-color: #ffffff;
708 715 padding: 10rpx 0;
709   - box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.03);
  716 + border-bottom: 1rpx solid #E8EBF0;
710 717 }
711 718  
  719 +/* 基本信息表单卡片:白底 16rpx 圆角 + 浅投影(设计稿 .card) */
712 720 .base-info-wrap {
713   - padding: 15px 15px;
714   - background: #fff;
  721 + margin: 24rpx;
  722 + padding: 8rpx 24rpx;
  723 + background-color: #ffffff;
  724 + border-radius: 16rpx;
  725 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  726 +}
  727 +.base-info-wrap :deep(.u-line) {
  728 + background-color: #EEF1F6;
  729 +}
  730 +/* 卡片内最后一行不画分隔线 */
  731 +.base-info-wrap :deep(.u-form-item:last-child .u-line) {
  732 + display: none;
  733 +}
  734 +/* 表单行:标签 28rpx 深色,输入值 26rpx 内容色 */
  735 +.base-info-wrap :deep(.u-form-item__body) {
  736 + padding: 24rpx 0 !important;
  737 +}
  738 +.base-info-wrap :deep(.u-form-item__body__left__content__label) {
  739 + font-size: 28rpx;
  740 + color: #1F2937;
  741 +}
  742 +.base-info-wrap :deep(.u-input__inner) {
  743 + font-size: 26rpx;
  744 + color: #4B5563;
  745 +}
  746 +
  747 +/* 分区标题:蓝色竖条 + 标题文字 */
  748 +.sec-head {
  749 + display: flex;
  750 + align-items: center;
  751 + gap: 12rpx;
  752 + padding: 20rpx 0 8rpx;
  753 +}
  754 +.sec-bar {
  755 + width: 6rpx;
  756 + height: 28rpx;
  757 + background-color: #2563EB;
  758 + border-radius: 3rpx;
  759 +}
  760 +.sec-title {
  761 + font-size: 30rpx;
  762 + font-weight: 500;
  763 + color: #1F2937;
  764 +}
  765 +/* 「显示区域」次要按钮:白底蓝字描边(设计稿 .btn.sec) */
  766 +.base-info-wrap :deep(.u-button--primary.u-button--plain) {
  767 + color: #2563EB !important;
  768 + border-color: #2563EB !important;
  769 + border-radius: 16rpx !important;
715 770 }
716 771  
717 772 .log-wrap, .inspect-wrap {
... ... @@ -719,39 +774,65 @@ const toAddInspect = () =&gt; {
719 774 }
720 775  
721 776 .record-wrap {
722   - padding-bottom: 20px;
  777 + padding: 24rpx 0 40rpx;
  778 +}
  779 +
  780 +/* 巡检 / 变更日志卡片:白底 16rpx 圆角 + 浅投影(设计稿 .tcard) */
  781 +.tree-card {
  782 + margin: 0 24rpx 24rpx !important;
  783 + border-radius: 16rpx !important;
  784 + background-color: #ffffff !important;
  785 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06) !important;
  786 +}
  787 +.tree-card :deep(.u-card__body) {
  788 + padding: 24rpx !important;
723 789 }
724 790  
725 791 .treetypeName {
726 792 flex: 1;
727   - font-size: 14px;
728   - font-weight: bold;
  793 + min-width: 0;
  794 + font-size: 30rpx;
  795 + font-weight: 500;
  796 + color: #1F2937;
729 797 }
730 798  
731 799 .record-list-left {
732   - height: 70px;
733   - width: 70px;
734   - background-size: 100% 100%;
  800 + width: 128rpx;
  801 + height: 128rpx;
  802 + border-radius: 12rpx;
  803 + background-color: #F4F6FA;
  804 + background-size: cover;
735 805 background-repeat: no-repeat;
736 806 background-position: center;
  807 + flex-shrink: 0;
737 808 }
738 809  
739 810 .record-list-right {
740   - margin-left: 20px;
  811 + margin-left: 24rpx;
741 812 flex: 1;
  813 + min-width: 0;
742 814 overflow: hidden;
743 815 }
744 816  
  817 +/* 树木编号:浅绿标签(设计稿 .tag.done) */
745 818 .treenumber-no {
746   - padding: 3px 10px;
747   - background: #bdefd0;
748   - font-size: 12px;
749   - margin-top: 8px;
  819 + display: inline-flex;
  820 + align-items: center;
  821 + height: 40rpx;
  822 + padding: 0 16rpx;
  823 + margin-top: 16rpx;
  824 + border-radius: 8rpx;
  825 + background-color: #EAF7EF;
  826 + color: #16A34A;
  827 + font-size: 22rpx;
  828 + font-weight: 500;
  829 + line-height: 1;
750 830 }
751 831  
752 832 .card-body-inner {
753 833 display: flex;
754   - font-size: 12px;
  834 + font-size: 26rpx;
  835 + color: #4B5563;
755 836 }
756 837  
757 838 .fs-align__center {
... ... @@ -783,7 +864,7 @@ const toAddInspect = () =&gt; {
783 864 left: 0;
784 865 bottom: -20rpx;
785 866 line-height: 20rpx;
786   - font-size: 22rpx;
  867 + font-size: 24rpx;
787 868 color: #f56c6c;
788 869 width: 100%;
789 870 box-sizing: border-box;
... ... @@ -807,11 +888,12 @@ const toAddInspect = () =&gt; {
807 888  
808 889 /* 巡检记录样式 */
809 890 .inspect-row {
810   - font-size: 14px;
811   - line-height: 2.2;
  891 + font-size: 26rpx;
  892 + line-height: 1.9;
  893 + color: #4B5563;
812 894 }
813 895 .detail-text {
814   - color: #1989fa;
815   - font-size: 14px;
  896 + color: #2563EB;
  897 + font-size: 24rpx;
816 898 }
817 899 </style>
818 900 \ No newline at end of file
... ...
pages-sub/data/tree-archive/index.vue
1 1 <template>
2 2 <view class="container">
3   - <!-- 归属单位选择 -->
4   - <up-form :model="formData" ref="formRef" label-width="140rpx" border-bottom style="padding: 0 15px">
5   - <up-form-item
6   - label="归属单位"
7   - prop="companyId"
8   - @click="showActionSheet = true"
9   - class="form-item-custom"
10   - >
11   - <up-input
12   - v-model="formData.companyId"
13   - placeholder="请选择归属单位"
14   - disabled
15   - disabled-color="#ffffff"
16   - border="none"
17   - bg-color="transparent"
  3 + <!-- 筛选条:归属单位 + 道路搜索(设计稿 .filter / .search-bar) -->
  4 + <view class="filter-bar">
  5 + <view class="sel" @click="showActionSheet = true">
  6 + <text class="sel-text up-line-1">{{ formData.companyId || '归属单位' }}</text>
  7 + <up-icon name="arrow-down" size="12" color="#9CA3AF"></up-icon>
  8 + </view>
  9 + <view class="sbox">
  10 + <up-icon name="search" size="12" color="#9CA3AF"></up-icon>
  11 + <input
  12 + v-model="searchValue"
  13 + class="sbox-input"
  14 + placeholder="请输入道路名称"
  15 + placeholder-class="sbox-placeholder"
  16 + confirm-type="search"
  17 + @confirm="handleSearch"
18 18 />
19   - <template #right>
20   - <up-icon name="arrow-right" size="16"></up-icon>
21   - </template>
22   - </up-form-item>
23   - </up-form>
24   -
25   - <!-- 弹窗式 Search 搜索组件 -->
26   - <view class="search-wrap">
27   - <up-search
28   - v-model="searchValue"
29   - placeholder="请输入道路名称搜索"
30   - @search="handleSearch"
31   - bg-color="#f5f5f5"
32   - :clearabled="false"
33   - :show-action="true"
34   - actionText="搜索"
35   - :animation="true"
36   - @custom="handleSearch"
37   - />
  19 + </view>
  20 + <text class="sbox-go" @click="handleSearch">搜索</text>
38 21 </view>
39 22  
40 23 <!-- ✅ 核心:uview-plus up-row+up-col 实现左右布局【无u-scroll-list,无任何多余组件】 -->
41 24 <up-row type="flex" class="cate-layout" align="flex-start">
42 25 <!-- 左侧:班组列表 (uview栅格列 + 原生滚动) -->
43 26 <up-col span="3" class="cate-left">
  27 + <!-- 补滚动容器:班组数量多时可滚动(.left-scroll 样式原本已定义但未挂载) -->
  28 + <scroll-view scroll-y class="left-scroll">
44 29 <view
45 30 class="left-item"
46 31 :class="{ active: currentIndex === index }"
... ... @@ -50,7 +35,7 @@
50 35 >
51 36 {{ item.deptName }}
52 37 </view>
53   -
  38 + </scroll-view>
54 39 </up-col>
55 40  
56 41 <!-- 右侧:道路列表 (uview栅格列 + 原生滚动) -->
... ... @@ -67,13 +52,35 @@
67 52 :key="item.roadId"
68 53 @click="toNewPage(item.roadId, item.treeCount)"
69 54 >
70   - <p class="fs-flex__between">
71   - <span class="up-line-1" style="color: #333;font-size: 14px">{{ item.roadName }}</span>
72   - <span class="treeCount" style="font-size: 14px">{{ item.treeCount }}棵</span>
73   - </p>
74   - <p class="up-line-1 fs-my8" style="color: #333;font-size: 14px">已录入行道树:{{ item.recordedCount }}棵</p>
75   - <p class="up-line-1 fs-my8" style="color: #999;font-size: 12px">起点:{{ item.startRemark }}</p>
76   - <p class="up-line-1" style="color: #999;font-size: 12px">终点:{{ item.endRemark }}</p>
  55 + <view class="card-head">
  56 + <text class="card-title up-line-1">{{ item.roadName }}</text>
  57 + <view class="tag-pending">{{ item.treeCount }} 棵</view>
  58 + </view>
  59 + <view class="card-body">
  60 + <view class="kv">
  61 + <text class="k">已录入行道树</text>
  62 + <text class="v up-line-1">{{ item.recordedCount }} / {{ item.treeCount }} 棵</text>
  63 + </view>
  64 + <!-- 录入进度:占总数比例,纯模板计算未新增 JS -->
  65 + <view class="progress">
  66 + <view
  67 + class="progress-bar"
  68 + :style="{ width: (item.treeCount ? (item.recordedCount / item.treeCount * 100) : 0) + '%' }"
  69 + ></view>
  70 + </view>
  71 + <view class="kv">
  72 + <text class="k">起点</text>
  73 + <text class="v up-line-1">{{ item.startRemark }}</text>
  74 + </view>
  75 + <view class="kv">
  76 + <text class="k">终点</text>
  77 + <text class="v up-line-1">{{ item.endRemark }}</text>
  78 + </view>
  79 + </view>
  80 + <view class="card-foot">
  81 + <text class="card-link">查看树木记录</text>
  82 + <up-icon name="arrow-right" size="10" color="#2563EB"></up-icon>
  83 + </view>
77 84 </view>
78 85 </view>
79 86 </scroll-view>
... ... @@ -193,32 +200,88 @@ const checkRoadDataValid = () =&gt; {
193 200 </script>
194 201  
195 202 <style scoped lang="scss">
196   -// 页面容器 满高布局
  203 +// 页面容器 满高布局(页面底 #F4F6FA,设计稿 --page-bg)
197 204 .container {
198 205 height: 100%;
199 206 display: flex;
200 207 flex-direction: column;
201   - background: #fff;
  208 + background-color: #F4F6FA;
  209 + box-sizing: border-box;
  210 +}
  211 +
  212 +// 筛选条:白底 + 1rpx 分隔线(设计稿 .filter / .search-bar)
  213 +.filter-bar {
  214 + flex-shrink: 0;
  215 + display: flex;
  216 + align-items: center;
  217 + gap: 16rpx;
  218 + padding: 24rpx;
  219 + background-color: #ffffff;
  220 + border-bottom: 1rpx solid #F0F0F0;
  221 +}
  222 +
  223 +// 归属单位选择框
  224 +.sel {
  225 + flex: 0 0 200rpx;
  226 + height: 60rpx;
  227 + display: flex;
  228 + align-items: center;
  229 + gap: 8rpx;
  230 + padding: 0 16rpx;
202 231 box-sizing: border-box;
  232 + border: 1rpx solid #E8EBF0;
  233 + border-radius: 8rpx;
  234 + background-color: #ffffff;
  235 +}
  236 +.sel-text {
  237 + flex: 1;
  238 + min-width: 0;
  239 + font-size: 26rpx;
  240 + color: #4B5563;
203 241 }
204 242  
205   -// 搜索框外层容器 间距不变
206   -.search-wrap {
207   - padding: 10rpx 15rpx;
  243 +// 道路搜索框
  244 +.sbox {
  245 + flex: 1;
  246 + min-width: 0;
  247 + height: 60rpx;
  248 + display: flex;
  249 + align-items: center;
  250 + gap: 12rpx;
  251 + padding: 0 20rpx;
  252 + box-sizing: border-box;
  253 + background-color: #F4F6FA;
  254 + border-radius: 8rpx;
  255 +}
  256 +.sbox-input {
  257 + flex: 1;
  258 + min-width: 0;
  259 + height: 100%;
  260 + font-size: 26rpx;
  261 + color: #1F2937;
  262 +}
  263 +.sbox-placeholder {
  264 + font-size: 26rpx;
  265 + color: #9CA3AF;
  266 +}
  267 +.sbox-go {
  268 + flex-shrink: 0;
  269 + font-size: 26rpx;
  270 + color: #2563EB;
208 271 }
209 272  
210 273 .cate-layout {
211 274 flex: 1;
  275 + min-height: 0;
212 276 width: 100%;
213   - height: calc(100vh - 44px);
214   -
215 277 }
216 278  
217 279  
218 280 .cate-left {
219 281 height: 100%;
220 282 padding: 0;
221   - background: #f8f8f8;
  283 + background: #F4F6FA;
  284 + border-right: 1rpx solid #F0F0F0;
222 285 box-sizing: border-box;
223 286 .left-scroll {
224 287 width: 100%;
... ... @@ -226,58 +289,132 @@ const checkRoadDataValid = () =&gt; {
226 289 }
227 290 // 左侧列表项
228 291 .left-item {
229   - padding: 24rpx 12rpx;
230   - font-size: 28rpx;
231   -
  292 + padding: 24rpx 20rpx;
  293 + font-size: 26rpx;
  294 + color: #4B5563;
232 295 white-space: nowrap;
233 296 overflow: hidden;
234 297 text-overflow: ellipsis;
235 298 box-sizing: border-box;
236 299 }
237   - // 选中项高亮 主题色和你一致 #5f5fe2
  300 + // 选中项高亮
238 301 .left-item.active {
239 302 background: #ffffff;
240   - color: #5f5fe2;
  303 + color: #2563EB;
241 304 font-weight: 500;
242   - border-left: 4rpx solid #5f5fe2;
  305 + border-left: 4rpx solid #2563EB;
243 306 }
244 307 }
245 308  
246 309 .cate-right {
247 310 height: 100%;
248   - padding: 0 10rpx;
  311 + padding: 0;
249 312 box-sizing: border-box;
250   - background: #ffffff;
  313 + background: #F4F6FA;
251 314 .right-scroll {
252 315 width: 100%;
253 316 height: 100%;
254 317 }
255 318 }
256 319  
257   -// 道路列表容器
  320 +// 道路列表容器:左右 20rpx、上 24rpx、下 48rpx 留白(设计稿 .right)
258 321 .road-list-wrap {
259   - //padding-bottom: 30rpx;
  322 + padding: 24rpx 20rpx 48rpx;
260 323 }
261 324  
262   -// 道路卡片样式 完全复用你的原版
  325 +// 道路卡片:白底 16rpx 圆角 + 浅投影(设计稿 .tcard)
263 326 .card-wrap {
264   - box-shadow:0 0 3px rgba(0, 0, 0, 0.2);
265   - padding: 20rpx;
266   - border-radius: 14rpx;
267   - background: #fff;
268   - margin:10px 6px;
  327 + padding: 24rpx;
  328 + border-radius: 16rpx;
  329 + background-color: #ffffff;
  330 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  331 + margin: 0 0 24rpx;
  332 +}
  333 +.card-wrap:last-child {
  334 + margin-bottom: 0;
  335 +}
  336 +
  337 +// 卡片标题行
  338 +.card-head {
  339 + display: flex;
  340 + align-items: center;
  341 + gap: 16rpx;
  342 +}
  343 +.card-title {
  344 + flex: 1;
  345 + min-width: 0;
  346 + font-size: 32rpx;
  347 + font-weight: 500;
  348 + color: #1F2937;
  349 +}
  350 +// 树木数量标签(设计稿 .tag.pending)
  351 +.tag-pending {
  352 + display: inline-flex;
  353 + align-items: center;
  354 + flex-shrink: 0;
  355 + height: 40rpx;
  356 + padding: 0 16rpx;
  357 + border-radius: 8rpx;
  358 + background-color: #EBF3FF;
  359 + color: #2563EB;
  360 + font-size: 22rpx;
  361 + font-weight: 500;
  362 + line-height: 1;
269 363 }
270 364  
271   -// 公共样式 完全不变
272   -.treeCount {
273   - color: #5f5fe2;
274   - min-width: 70px;
  365 +// 键值行(设计稿 .kv)
  366 +.card-body {
  367 + display: flex;
  368 + flex-direction: column;
  369 + gap: 6rpx;
  370 + margin-top: 20rpx;
  371 +}
  372 +.kv {
  373 + display: flex;
  374 + align-items: flex-start;
  375 + gap: 16rpx;
  376 + padding: 2rpx 0;
  377 + font-size: 26rpx;
  378 + line-height: 1.5;
  379 +}
  380 +.kv .k {
  381 + flex-shrink: 0;
  382 + color: #9CA3AF;
  383 +}
  384 +.kv .v {
  385 + flex: 1;
  386 + min-width: 0;
  387 + color: #4B5563;
275 388 text-align: right;
276 389 }
277   -.fs-flex__between {
  390 +
  391 +// 录入进度条:直观呈现「已录入 / 总数」
  392 +.progress {
  393 + height: 8rpx;
  394 + border-radius: 4rpx;
  395 + background-color: #F4F6FA;
  396 + overflow: hidden;
  397 + margin: 8rpx 0 4rpx;
  398 +}
  399 +.progress-bar {
  400 + height: 100%;
  401 + border-radius: 4rpx;
  402 + background-color: #2563EB;
  403 + transition: width 0.3s ease;
  404 +}
  405 +
  406 +// 卡片底部操作区(设计稿 .tcard-foot)
  407 +.card-foot {
278 408 display: flex;
279   - justify-content: space-between;
280 409 align-items: center;
  410 + justify-content: flex-end;
  411 + gap: 8rpx;
  412 + margin-top: 20rpx;
  413 + padding-top: 20rpx;
  414 + border-top: 1rpx solid #F0F0F0;
  415 +}
  416 +.card-link {
  417 + font-size: 24rpx;
  418 + color: #2563EB;
281 419 }
282   -.fs-my8 { margin: 8rpx 0; }
283 420 </style>
284 421 \ No newline at end of file
... ...
pages-sub/data/tree-archive/inspectDetail.vue
... ... @@ -14,7 +14,7 @@
14 14 <style scoped>
15 15 .inspect-detail {
16 16 min-height: 100vh;
17   - background: #f5f7fa;
  17 + background-color: #F4F6FA;
18 18 }
19 19 .content {
20 20 padding: 30rpx;
... ... @@ -22,6 +22,6 @@
22 22 }
23 23 .empty-tip {
24 24 font-size: 14px;
25   - color: #999;
  25 + color: #909399;
26 26 }
27 27 </style>
28 28 \ No newline at end of file
... ...
pages-sub/data/tree-archive/logDetail.vue
1 1 <template>
2 2 <view class="page-container">
3 3 <up-form :model="formData" ref="formRef" label-width="140rpx" border-bottom>
  4 + <!-- 分区标题:蓝色竖条 + 标题文字(设计稿 .fgrp-title) -->
  5 + <view class="sec-head">
  6 + <view class="sec-bar"></view>
  7 + <text class="sec-title">基础信息</text>
  8 + </view>
  9 +
4 10 <up-form-item label="名称" prop="treetype" required>
5 11 <up-input v-model="formData.treetype" border="none" readonly placeholder=""/>
6 12 </up-form-item>
... ... @@ -18,7 +24,7 @@
18 24 <up-form-item label="胸径" prop="dbh" required>
19 25 <up-input v-model="formData.dbh" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
20 26 <template #right>
21   - <text style="padding-left: 12rpx;color:#ccc;font-size:14px">厘米</text>
  27 + <text style="padding-left: 12rpx;color:#9CA3AF;font-size:26rpx">厘米</text>
22 28 </template>
23 29 </up-form-item>
24 30 </up-col>
... ... @@ -26,7 +32,7 @@
26 32 <up-form-item label="高度" prop="treeheight">
27 33 <up-input v-model="formData.treeheight" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
28 34 <template #right>
29   - <text style="padding-left: 12rpx;color:#ccc;font-size:14px;">米</text>
  35 + <text style="padding-left: 12rpx;color:#9CA3AF;font-size:26rpx;">米</text>
30 36 </template>
31 37 </up-form-item>
32 38 </up-col>
... ... @@ -101,7 +107,7 @@
101 107 <up-form-item label="干周" prop="weekday">
102 108 <up-input v-model="formData.weekday" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
103 109 <template #right>
104   - <text style="padding-left:12rpx;color:#ccc;font-size:14px">厘米</text>
  110 + <text style="padding-left:12rpx;color:#9CA3AF;font-size:26rpx">厘米</text>
105 111 </template>
106 112 </up-form-item>
107 113 </up-col>
... ... @@ -114,7 +120,7 @@
114 120 <up-form-item label="东西冠幅" prop="canopyeastwest">
115 121 <up-input v-model="formData.canopyeastwest" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
116 122 <template #right>
117   - <text style="padding-left:12rpx;color:#ccc;font-size:14px">米</text>
  123 + <text style="padding-left:12rpx;color:#9CA3AF;font-size:26rpx">米</text>
118 124 </template>
119 125 </up-form-item>
120 126 </up-col>
... ... @@ -122,7 +128,7 @@
122 128 <up-form-item label="南北冠幅" prop="canopysouthnorth">
123 129 <up-input v-model="formData.canopysouthnorth" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
124 130 <template #right>
125   - <text style="padding-left:12rpx;color:#ccc;font-size:14px">米</text>
  131 + <text style="padding-left:12rpx;color:#9CA3AF;font-size:26rpx">米</text>
126 132 </template>
127 133 </up-form-item>
128 134 </up-col>
... ... @@ -216,10 +222,54 @@ onReady(() =&gt; {});
216 222 </script>
217 223  
218 224 <style scoped lang="scss">
  225 +/* 页面底色 + 留白(设计稿 --page-bg / .body) */
219 226 .page-container {
220   - padding: 25rpx;
  227 + padding: 24rpx;
221 228 box-sizing: border-box;
222   - background: #fff;
  229 + background-color: #F4F6FA;
  230 +}
  231 +
  232 +/* 表单整体作为白色卡片:16rpx 圆角 + 浅投影(设计稿 .card) */
  233 +.page-container :deep(.u-form) {
  234 + padding: 8rpx 24rpx;
  235 + background-color: #ffffff;
  236 + border-radius: 16rpx;
  237 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  238 +}
  239 +.page-container :deep(.u-line) {
  240 + background-color: #EEF1F6;
  241 +}
  242 +/* 卡片内最后一行不画分隔线 */
  243 +.page-container :deep(.u-form-item:last-child .u-line) {
  244 + display: none;
  245 +}
  246 +
  247 +/* 分区标题:蓝色竖条 + 标题文字 */
  248 +.sec-head {
  249 + display: flex;
  250 + align-items: center;
  251 + gap: 12rpx;
  252 + padding: 20rpx 0 8rpx;
  253 +}
  254 +.sec-bar {
  255 + width: 6rpx;
  256 + height: 28rpx;
  257 + background-color: #2563EB;
  258 + border-radius: 3rpx;
  259 +}
  260 +.sec-title {
  261 + font-size: 30rpx;
  262 + font-weight: 500;
  263 + color: #1F2937;
  264 +}
  265 +
  266 +/* 表单行:标签 28rpx 深色,内容值 26rpx 内容色 */
  267 +.page-container :deep(.u-form-item__body) {
  268 + padding: 24rpx 0 !important;
  269 +}
  270 +.page-container :deep(.u-form-item__body__left__content__label) {
  271 + font-size: 28rpx;
  272 + color: #1F2937;
223 273 }
224 274  
225 275 .location-form-item {
... ... @@ -227,13 +277,14 @@ onReady(() =&gt; {});
227 277 }
228 278  
229 279 :deep(.u-input__inner) {
230   - color: #333;
  280 + font-size: 26rpx;
  281 + color: #4B5563;
231 282 background-color: transparent !important;
232 283 }
233 284  
234 285 .show-text {
235   - font-size: 28rpx;
236   - color: #333;
  286 + font-size: 26rpx;
  287 + color: #4B5563;
237 288 line-height: 80rpx;
238 289 width: 100%;
239 290 display: block;
... ...
pages-sub/data/tree-archive/treeRecord.vue
... ... @@ -33,20 +33,19 @@
33 33 <view class="record-list-right">
34 34 <view class="up-flex up-flex-items-center up-flex-between">
35 35 <view class="u-line-1 treetypeName">{{ i.treetype }}</view>
36   - <view style="text-align: right">{{ timeFormat(i.updatetime) }}</view>
  36 + <view class="record-time">{{ timeFormat(i.updatetime) }}</view>
37 37 </view>
38   - <view class="up-flex up-flex-items-center" style="margin: 8px 0">
39   - <img src="../../../static/imgs/tree/tree-high.png" style="width: 12px;height: 12px;margin-right: 6px;"
40   - alt=""> 高度:{{ i.treeheight }} 米
  38 + <view class="record-kv">
  39 + <img src="../../../static/imgs/tree/tree-high.png" class="record-ico" alt=""> 高度:{{ i.treeheight }} 米
41 40 </view>
42   - <view class="up-flex up-flex-items-center">
43   - <img src="../../../static/imgs/tree/treearound.png"
44   - style="width: 12px;height: 12px;margin-right: 6px;" alt="">胸径:{{ i.dbh }} 厘米
  41 + <view class="record-kv">
  42 + <img src="../../../static/imgs/tree/treearound.png" class="record-ico" alt="">胸径:{{ i.dbh }} 厘米
45 43 </view>
46 44 </view>
47 45 </view>
48   - <view class="treenumber-no">
49   - 树木编号:{{ i.treenumber }}
  46 + <view class="record-foot">
  47 + <view class="record-tag">树木编号:{{ i.treenumber }}</view>
  48 + <text class="record-link">查看</text>
50 49 </view>
51 50 </template>
52 51 </up-card>
... ... @@ -111,62 +110,105 @@ const fetchData = async (pageNo, pageSize) =&gt; {
111 110 </script>
112 111  
113 112 <style scoped lang="scss">
114   -// ✅ 你的原始样式 一行没删、一行没改、全部保留
  113 +/* 页面底色(设计稿 --page-bg) */
115 114 .page-container {
116 115 min-height: 100vh;
  116 + background-color: #F4F6FA;
  117 + box-sizing: border-box;
117 118 }
118 119  
  120 +/* 列表:左右 24rpx 留白,卡片之间 24rpx(设计稿 .body) */
119 121 .record-wrap {
120   - padding-bottom: 20px;
  122 + padding: 24rpx 0 180rpx; // 底部预留固定按钮高度
121 123 }
122 124  
123   -.record-list-wrap {
124   - margin: 15px 10px 0;
125   - padding: 10px;
126   - border-radius: 6px;
127   - font-size: 14px;
  125 +/* 树木卡片:白底 16rpx 圆角 + 浅投影(设计稿 .tcard) */
  126 +.tree-card {
  127 + margin: 0 24rpx 24rpx !important;
  128 + border-radius: 16rpx !important;
  129 + background-color: #ffffff !important;
  130 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06) !important;
  131 +}
  132 +.tree-card :deep(.u-card__body) {
  133 + padding: 24rpx !important;
128 134 }
129 135  
130   -.treetypeName {
131   - flex: 1;
132   - font-size: 14px;
133   - font-weight: bold;
  136 +.card-body-inner {
  137 + display: flex;
  138 + font-size: 26rpx;
134 139 }
135 140  
136 141 .record-list-left {
137   - height: 70px;
138   - width: 70px;
139   - background-size: 100% 100%;
140   - background-repeat: no-repeat; // 新增:防止图片平铺
141   - background-position: center; // 新增:图片居中显示
  142 + width: 128rpx;
  143 + height: 128rpx;
  144 + border-radius: 12rpx;
  145 + background-color: #F4F6FA;
  146 + background-size: cover;
  147 + background-repeat: no-repeat;
  148 + background-position: center;
  149 + flex-shrink: 0;
142 150 }
143 151  
144 152 .record-list-right {
145   - margin-left: 20px;
  153 + margin-left: 24rpx;
146 154 flex: 1;
  155 + min-width: 0;
147 156 overflow: hidden;
148 157 }
149 158  
150   -
151   -.treenumber-no {
152   - margin-top: 5px;
153   - padding: 3px 10px;
154   - background: #bdefd0;
155   - font-size: 12px;
  159 +.treetypeName {
  160 + flex: 1;
  161 + min-width: 0;
  162 + font-size: 30rpx;
  163 + font-weight: 500;
  164 + color: #1F2937;
156 165 }
157 166  
  167 +.record-time {
  168 + flex-shrink: 0;
  169 + margin-left: 16rpx;
  170 + font-size: 22rpx;
  171 + color: #9CA3AF;
  172 +}
158 173  
159   -// ✅ 只加了这2个适配up-card的样式,无其他修改
160   -.tree-card {
161   - //margin: 15px 10px 0;
162   - //
163   - //border-radius: 6px;
164   - //box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
165   - //background: #fff;
  174 +.record-kv {
  175 + display: flex;
  176 + align-items: center;
  177 + margin-top: 10rpx;
  178 + font-size: 24rpx;
  179 + color: #4B5563;
  180 +}
  181 +.record-ico {
  182 + width: 24rpx;
  183 + height: 24rpx;
  184 + margin-right: 8rpx;
166 185 }
167 186  
168   -.card-body-inner {
  187 +/* 卡片底部:编号标签 + 查看(设计稿 .tcard-foot) */
  188 +.record-foot {
169 189 display: flex;
170   - font-size: 12px;
  190 + align-items: center;
  191 + justify-content: space-between;
  192 + gap: 16rpx;
  193 + margin-top: 16rpx;
  194 + padding-top: 16rpx;
  195 + border-top: 1rpx solid #E8EBF0;
  196 +}
  197 +.record-tag {
  198 + display: inline-flex;
  199 + align-items: center;
  200 + height: 40rpx;
  201 + padding: 0 16rpx;
  202 + border-radius: 8rpx;
  203 + background-color: #EAF7EF;
  204 + color: #16A34A;
  205 + font-size: 22rpx;
  206 + font-weight: 500;
  207 + line-height: 1;
  208 +}
  209 +.record-link {
  210 + flex-shrink: 0;
  211 + font-size: 24rpx;
  212 + color: #2563EB;
171 213 }
172 214 </style>
173 215 \ No newline at end of file
... ...
pages-sub/msg/index.vue
... ... @@ -21,10 +21,10 @@
21 21 <template #body>
22 22 <view class="card-body">
23 23 <view class="u-flex common-item-center common-justify-between" style="margin-top: 5px;">
24   - <view class="u-line-1" style="flex: 1;margin-right: 20px;color: #333;font-size: 14px;"> {{ item.templateCode || '无' }}</view>
25   - <view style="color: #030303;font-size: 12px;" >{{ timeFormat(item.createTime, 'yyyy-mm-dd') }}</view>
  24 + <view class="u-line-1" style="flex: 1;margin-right: 20px;color: #1a1a1a;font-size: 14px;"> {{ item.templateCode || '无' }}</view>
  25 + <view style="color: #1a1a1a;font-size: 12px;" >{{ timeFormat(item.createTime, 'yyyy-mm-dd') }}</view>
26 26 </view>
27   - <view class="u-line-1 " style="font-size: 13px;color: #848484">
  27 + <view class="u-line-1 " style="font-size: 14px;color: #909399">
28 28 {{ item.templateContent || '无' }}
29 29 </view>
30 30  
... ... @@ -73,6 +73,13 @@ onShow( async () =&gt; {
73 73  
74 74 <style lang="scss" scoped>
75 75  
  76 +/* 页面底色:统一浅灰蓝(设计稿 --page-bg) */
  77 +.user-center-page {
  78 + min-height: 100vh;
  79 + background-color: #F4F6FA;
  80 + box-sizing: border-box;
  81 +}
  82 +
76 83 </style>
77 84 <script setup lang="ts">
78 85 </script>
79 86 \ No newline at end of file
... ...
pages-sub/problem/ai-manage/index.vue
... ... @@ -6,8 +6,8 @@
6 6 <up-tabs
7 7 v-model="activeTab"
8 8 :list="tabList"
9   - active-color="#1989fa"
10   - inactive-color="#666"
  9 + active-color="#2563EB"
  10 + inactive-color="#606266"
11 11 font-size="30rpx"
12 12 @click="handleTabChange"
13 13 />
... ... @@ -51,7 +51,7 @@
51 51 <empty-view />
52 52 </template>
53 53  
54   - <view class="common-card-list" style="padding-top: 200rpx;padding-bottom: 30rpx">
  54 + <view class="common-card-list" style="padding-top: 216rpx;padding-bottom: 180rpx">
55 55 <!-- 待办工单卡片 -->
56 56 <up-card
57 57 v-if="activeTab === 0"
... ... @@ -95,15 +95,16 @@
95 95 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
96 96 </view>
97 97 <!-- 操作按钮行:已配置工作流动作时按配置逐个渲染按钮,点击直接执行对应动作 -->
98   - <view class="u-body-item task-btn-row mt-20">
  98 + <view class="u-body-item task-btn-row mt-20"
  99 + :style="{'--cols': getActionRowCols(actionBtnCount(item))}">
99 100 <template v-if="hasConfiguredActions(item)">
100 101 <view
101 102 v-for="action in item.configuredActions"
102 103 :key="action.code"
103   - :class="['task-btn', 'task-btn--' + getActionButtonType(action.code)]"
  104 + :class="['task-btn', 'task-btn--' + getActionButtonType(action.code, action.name)]"
104 105 @click.stop="handleUnifiedProcess(item, action)"
105 106 >{{ action.name }}</view>
106   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  107 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
107 108 </template>
108 109 <!-- 未配置:沿用原有节点按钮 -->
109 110 <template v-else>
... ... @@ -111,7 +112,7 @@
111 112 @click.stop="handleUnifiedReject(item)">回退</view>
112 113 <view class="task-btn task-btn--primary"
113 114 @click.stop="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</view>
114   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  115 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
115 116 </template>
116 117 </view>
117 118 </view>
... ... @@ -130,9 +131,6 @@
130 131 >
131 132 <template #body>
132 133 <view class="card-body">
133   - <view class="common-custom-btn " style="--btn-top: 130px;" @click="handleDetail(item)">
134   - 工单详情
135   - </view>
136 134 <view class="u-body-item u-flex">
137 135 <view class="u-body-item-title">工单编号:</view>
138 136 <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view>
... ... @@ -165,6 +163,11 @@
165 163 <view class="u-body-item-title">提交时间:</view>
166 164 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
167 165 </view>
  166 +
  167 + <!-- 底部操作:分隔线 + 查看详情(与工单管理列表统一) -->
  168 + <view class="card-foot">
  169 + <view class="foot-btn" @click="handleDetail(item)">工单详情</view>
  170 + </view>
168 171 </view>
169 172 </template>
170 173 </up-card>
... ... @@ -276,7 +279,7 @@ import {
276 279 } from '@/api/regional-order-manage/regional-order-manage'
277 280 import { getTaskActions } from '@/api/work-order-manage/work-order-manage'
278 281 import { useUserStore } from '@/pinia/user';
279   -import { nextStepMap, buzStatusMap, getActionButtonType, toWorkerImplementPage } from '@/common/utils/common'
  282 +import { nextStepMap, buzStatusMap, getActionButtonType, getActionRowCols, toWorkerImplementPage } from '@/common/utils/common'
280 283 import { useUploadImgs } from '@/common/utils/useUploadImgs'
281 284  
282 285 // ========== 全局实例 & 常量 ==========
... ... @@ -510,6 +513,16 @@ const getProcessButtonText = (item) =&gt; {
510 513 const hasConfiguredActions = (item) =>
511 514 Array.isArray(item?.configuredActions) && item.configuredActions.length > 0
512 515  
  516 +/** 操作按钮行按钮数量:单个占一半宽度,多个等分,最多 5 个一行 */
  517 +const actionBtnCount = (item) => {
  518 + if (hasConfiguredActions(item)) {
  519 + return item.configuredActions.length + 1 // 配置动作 + 详情
  520 + }
  521 + let count = 2 // 主按钮 + 详情
  522 + if (showRejectButton(item)) count++
  523 + return count
  524 +}
  525 +
513 526 /** 待办-处理工单:已配置统一动作时直接执行点击的配置动作,否则回退原有处理 */
514 527 const handleUnifiedProcess = async (item, action = null) => {
515 528 const actions = Array.isArray(item?.configuredActions)
... ... @@ -712,7 +725,7 @@ onShow(() =&gt; {
712 725 <style scoped lang="scss">
713 726 .page-container {
714 727 min-height: 100vh;
715   - background-color: #fafafa;
  728 + background-color: #F4F6FA;
716 729 }
717 730  
718 731 // 顶部固定区域
... ... @@ -743,17 +756,47 @@ onShow(() =&gt; {
743 756  
744 757 // 工单卡片样式
745 758 .order-card {
746   - margin: 0 20rpx 20rpx;
747   - background: #fff;
748   - border-radius: 12rpx;
749   - box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
  759 + margin: 0 24rpx 24rpx;
  760 + background-color: #ffffff;
  761 + border-radius: 16rpx;
  762 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
750 763 }
751 764  
752   -// 卡片操作按钮:自动换行、右对齐,动作多时每行 3~4 个,不再整行铺满
753   -.task-btn-row {
  765 +// 底部操作区:分隔线 + 工单详情按钮(与工单管理列表统一)
  766 +.card-foot {
754 767 display: flex;
755   - flex-wrap: wrap;
756 768 justify-content: flex-end;
  769 + margin-top: 24rpx;
  770 + padding-top: 24rpx;
  771 + border-top: 1rpx solid #E8EBF0;
  772 +}
  773 +
  774 +.foot-btn {
  775 + box-sizing: border-box;
  776 + display: flex;
  777 + align-items: center;
  778 + justify-content: center;
  779 + min-width: 140rpx;
  780 + height: 56rpx;
  781 + padding: 0 24rpx;
  782 + font-size: 24rpx;
  783 + color: #ffffff;
  784 + background-color: #3B9DFF; // 与「详情」按钮统一蓝色
  785 + border: 1rpx solid #3B9DFF;
  786 + border-radius: 8rpx;
  787 +}
  788 +
  789 +.foot-btn:active {
  790 + background-color: #2E8AE6;
  791 + border-color: #2E8AE6;
  792 +}
  793 +
  794 +// 卡片操作按钮:单个占一半宽度,多个等分,每行最多 5 个
  795 +.task-btn-row {
  796 + display: grid;
  797 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  798 + column-gap: 12rpx;
  799 + row-gap: 10rpx;
757 800 margin-bottom: -10rpx;
758 801 }
759 802  
... ... @@ -761,20 +804,31 @@ onShow(() =&gt; {
761 804 box-sizing: border-box;
762 805 height: 56rpx;
763 806 line-height: 56rpx;
764   - padding: 0 24rpx;
765   - margin: 0 0 10rpx 12rpx;
  807 + padding: 0 12rpx;
766 808 border-radius: 8rpx;
767 809 font-size: 24rpx;
768 810 color: #fff;
  811 + text-align: center;
769 812 white-space: nowrap;
  813 + overflow: hidden;
  814 + text-overflow: ellipsis;
770 815 }
771 816  
  817 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
772 818 .task-btn--primary {
773   - background-color: #3c9cff;
  819 + background-color: #3B9DFF;
  820 +}
  821 +
  822 +.task-btn--assign {
  823 + background-color: #2563EB;
  824 +}
  825 +
  826 +.task-btn--transfer {
  827 + background-color: #0891B2;
774 828 }
775 829  
776 830 .task-btn--success {
777   - background-color: #5ac725;
  831 + background-color: #078d0a;
778 832 }
779 833  
780 834 .task-btn--warning {
... ... @@ -789,7 +843,6 @@ onShow(() =&gt; {
789 843 background-color: #909399;
790 844 }
791 845  
792   -
793 846 // 弹窗公共样式
794 847 .reject-modal-content, .accept-modal-content {
795 848 width: 100%;
... ... @@ -800,7 +853,7 @@ onShow(() =&gt; {
800 853 .upload-wrap {
801 854 .upload-title {
802 855 font-size: 28rpx;
803   - color: #333;
  856 + color: #1a1a1a;
804 857 margin-bottom: 10rpx;
805 858 }
806 859 }
... ...
pages-sub/problem/regional-order-manage/add-order.vue
1 1 <template>
2 2 <view class="page-container">
3   - <view class="work-order-form-content commonPageLRpadding">
  3 + <view class="work-order-form-content">
4 4 <up-form
5 5 label-position="left"
6 6 :model="baseForm"
7 7 ref="workOrderFormRef"
8 8 labelWidth="200rpx"
9 9 >
  10 + <!-- 报单信息 -->
  11 + <view class="form-card">
  12 + <view class="sec-head">
  13 + <view class="sec-bar"></view>
  14 + <view class="sec-title">报单信息</view>
  15 + </view>
  16 +
10 17 <!-- 1. 工单位置(地图选择)【公共项】 -->
11 18 <up-form-item
12 19 label="工单位置"
13 20 prop="workLocation"
14 21 border-bottom
15 22 required
  23 + class="form-item"
16 24 @click="chooseWorkLocation(); hideKeyboard()"
17 25 >
18 26 <up-input
... ... @@ -30,6 +38,7 @@
30 38 prop="problemDesc"
31 39 required
32 40 border-bottom
  41 + class="form-item"
33 42 >
34 43 <up-textarea
35 44 placeholder="请输入情况描述(最多200字)"
... ... @@ -42,7 +51,7 @@
42 51 </up-form-item>
43 52  
44 53 <!-- 3. 问题照片【公共项】 -->
45   - <up-form-item label="问题照片" prop="problemImgs" required >
  54 + <up-form-item label="问题照片" prop="problemImgs" required class="form-item">
46 55 <up-upload
47 56 :file-list="problemImgs.imgList.value || []"
48 57 @after-read="problemImgs.uploadImgs"
... ... @@ -55,6 +64,7 @@
55 64 :size-type="problemImgs.uploadConfig.sizeType"
56 65 ></up-upload>
57 66 </up-form-item>
  67 + </view>
58 68  
59 69 <!-- 多组派单区域 -->
60 70 <view class="dispatch-list-wrap">
... ... @@ -827,45 +837,111 @@ if (hasRepeat) {
827 837 </script>
828 838  
829 839 <style lang="scss" scoped>
  840 +/* 统一卡片样式(与工单表单页一致) */
830 841 .page-container {
831 842 min-height: 100vh;
832   - padding-bottom: 100rpx;
833   - background: #fafafa;
  843 + padding-bottom: 200rpx;
  844 + background-color: #F4F6FA;
  845 + box-sizing: border-box;
834 846 }
835 847  
836 848 .work-order-form-content {
837   - background: #fff;
  849 + padding: 0 24rpx;
  850 + background: transparent;
  851 +}
  852 +
  853 +.form-item {
  854 + margin-bottom: 20rpx;
  855 +}
  856 +
  857 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  858 +.form-card {
  859 + margin-top: 24rpx;
  860 + padding: 8rpx 24rpx;
  861 + background-color: #ffffff;
  862 + border-radius: 16rpx;
  863 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
838 864 }
839 865  
  866 +// 区块标题:蓝色竖条 + 标题文字
  867 +.sec-head {
  868 + display: flex;
  869 + align-items: center;
  870 + gap: 12rpx;
  871 + padding: 20rpx 0 8rpx;
  872 +}
  873 +.sec-bar {
  874 + width: 6rpx;
  875 + height: 28rpx;
  876 + background-color: #2563EB;
  877 + border-radius: 3rpx;
  878 +}
  879 +.sec-title {
  880 + font-size: 30rpx;
  881 + font-weight: 500;
  882 + color: #1F2937;
  883 +}
  884 +
  885 +// 表单行:上下 24rpx(左右由卡片内边距控制)
  886 +.form-card .form-item {
  887 + margin-bottom: 0;
  888 +}
  889 +.form-card :deep(.u-form-item__body) {
  890 + padding: 24rpx 0 !important;
  891 +}
  892 +.form-card :deep(.u-form-item__body__left__content__label) {
  893 + font-size: 28rpx;
  894 + color: #333333;
  895 +}
  896 +.form-card :deep(.u-line) {
  897 + background-color: #EEF1F6;
  898 +}
  899 +/* 卡片内最后一行不画分隔线 */
  900 +.form-card :deep(.u-form-item:last-child .u-line) {
  901 + display: none;
  902 +}
  903 +
  904 +/* 派单区域 */
840 905 .dispatch-list-wrap {
841   - padding-top: 24rpx;
842   - margin-top: 8rpx;
843   - border-top: 1px solid #f5f5f5;
  906 + padding-top: 8rpx;
844 907 }
845 908  
846 909 .dispatch-title {
847   - font-size: 32rpx;
848   - font-weight: 600;
849   - color: $u-primary;
850   - margin-bottom: 20rpx;
851   - padding-left: 10rpx;
  910 + position: relative;
  911 + margin: 24rpx 0 16rpx;
  912 + padding-left: 18rpx;
  913 + font-size: 30rpx;
  914 + font-weight: 500;
  915 + color: #1F2937;
  916 +}
  917 +.dispatch-title::before {
  918 + content: '';
  919 + position: absolute;
  920 + left: 0;
  921 + top: 50%;
  922 + transform: translateY(-50%);
  923 + width: 6rpx;
  924 + height: 28rpx;
  925 + background-color: #2563EB;
  926 + border-radius: 3rpx;
852 927 }
853 928  
854 929 .dispatch-item {
855 930 position: relative;
856   - border: 1px solid #eee;
857   - border-radius: 12rpx;
858   - padding: 20rpx;
859   - margin-bottom: 20rpx;
860   - background: #fdfdfd;
  931 + margin-bottom: 24rpx;
  932 + padding: 8rpx 24rpx;
  933 + background-color: #ffffff;
  934 + border-radius: 16rpx;
  935 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
861 936  
862 937 .item-head {
863 938 display: flex;
864 939 justify-content: space-between;
865 940 align-items: center;
866   - margin-bottom: 16rpx;
867   - font-size: 28rpx;
  941 + padding: 20rpx 0 8rpx;
  942 + font-size: 30rpx;
868 943 font-weight: 500;
  944 + color: #1F2937;
869 945 }
870 946  
871 947 .close-icon {
... ... @@ -875,6 +951,20 @@ if (hasRepeat) {
875 951 }
876 952 }
877 953  
  954 +.dispatch-item :deep(.u-form-item__body) {
  955 + padding: 24rpx 0 !important;
  956 +}
  957 +.dispatch-item :deep(.u-form-item__body__left__content__label) {
  958 + font-size: 28rpx;
  959 + color: #333333;
  960 +}
  961 +.dispatch-item :deep(.u-line) {
  962 + background-color: #EEF1F6;
  963 +}
  964 +.dispatch-item :deep(.u-form-item:last-child .u-line) {
  965 + display: none;
  966 +}
  967 +
878 968 .add-dispatch-btn-wrap {
879 969 margin: 20rpx 0;
880 970 }
... ...
pages-sub/problem/regional-order-manage/add-patrol-order.vue
1 1 <template>
2 2 <view class="page-container">
3   - <view class="work-order-form-content commonPageLRpadding">
  3 + <view class="work-order-form-content">
4 4 <up-form label-position="left" :model="workOrderForm" ref="workOrderFormRef" labelWidth="200rpx">
  5 + <view class="form-card">
  6 + <view class="sec-head">
  7 + <view class="sec-bar"></view>
  8 + <view class="sec-title">报单信息</view>
  9 + </view>
  10 +
5 11 <!-- 1. 工单位置(地图选择) -->
6   - <up-form-item label="工单位置" prop="workLocation" border-bottom required
  12 + <up-form-item label="工单位置" prop="workLocation" border-bottom required class="form-item"
7 13 @click="chooseWorkLocation(); hideKeyboard()">
8 14 <up-input v-model="workOrderForm.workLocation" border="none" readonly suffix-icon="map-fill"
9 15 placeholder="点击选择工单位置"></up-input>
10 16 </up-form-item>
11 17  
12 18 <!-- 2. 问题类型(下拉框) -->
13   - <up-form-item label="问题类型" prop="orderName" border-bottom required
  19 + <up-form-item label="问题类型" prop="orderName" border-bottom required class="form-item"
14 20 @click="handleActionSheetOpen('orderName'); hideKeyboard()">
15 21 <up-input v-model="workOrderForm.orderName" disabled disabled-color="#ffffff" placeholder="请选择问题类型"
16 22 border="none"></up-input>
... ... @@ -20,18 +26,25 @@
20 26 </up-form-item>
21 27  
22 28 <!-- 3. 情况描述(文本域) -->
23   - <up-form-item label="情况描述" prop="problemDesc" required>
  29 + <up-form-item label="情况描述" prop="problemDesc" required class="form-item">
24 30 <up-textarea placeholder="请输入情况描述(最多200字)" v-model.trim="workOrderForm.problemDesc" count maxlength="200"
25 31 rows="4" @blur="() => workOrderFormRef.validateField('problemDesc')"></up-textarea>
26 32 </up-form-item>
  33 + </view>
27 34  
28 35 <!-- 4. 问题照片 -->
29   - <up-form-item label="问题照片" prop="problemImgs" required>
30   - <up-upload :file-list="problemImgs.imgList.value || []" @after-read="problemImgs.uploadImgs"
31   - @delete="problemImgs.deleteImg" multiple :width="70" :height="70"
32   - :max-count="problemImgs.uploadConfig.maxCount" :upload-text="problemImgs.uploadConfig.uploadText"
33   - :size-type="problemImgs.uploadConfig.sizeType"></up-upload>
34   - </up-form-item>
  36 + <view class="form-card">
  37 + <view class="sec-head">
  38 + <view class="sec-bar"></view>
  39 + <view class="sec-title">问题照片</view>
  40 + </view>
  41 + <up-form-item label="问题照片" prop="problemImgs" required class="form-item">
  42 + <up-upload :file-list="problemImgs.imgList.value || []" @after-read="problemImgs.uploadImgs"
  43 + @delete="problemImgs.deleteImg" multiple :width="70" :height="70"
  44 + :max-count="problemImgs.uploadConfig.maxCount" :upload-text="problemImgs.uploadConfig.uploadText"
  45 + :size-type="problemImgs.uploadConfig.sizeType"></up-upload>
  46 + </up-form-item>
  47 + </view>
35 48  
36 49 </up-form>
37 50 </view>
... ... @@ -352,13 +365,65 @@ const submitWorkOrder = async () =&gt; {
352 365 </script>
353 366  
354 367 <style lang="scss" scoped>
355   -// 全局页面样式
  368 +/* 统一卡片样式(与工单表单页一致) */
356 369 .page-container {
357 370 min-height: 100vh;
  371 + padding-bottom: 200rpx;
  372 + background-color: #F4F6FA;
  373 + box-sizing: border-box;
358 374 }
359 375  
360   -// 工单表单内容容器
361 376 .work-order-form-content {
362   - background: #fff;
  377 + padding: 0 24rpx;
  378 + background: transparent;
  379 +}
  380 +
  381 +.form-item {
  382 + margin-bottom: 0;
  383 +}
  384 +
  385 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  386 +.form-card {
  387 + margin-top: 24rpx;
  388 + padding: 8rpx 24rpx;
  389 + background-color: #ffffff;
  390 + border-radius: 16rpx;
  391 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  392 +}
  393 +
  394 +// 区块标题:蓝色竖条 + 标题文字
  395 +.sec-head {
  396 + display: flex;
  397 + align-items: center;
  398 + gap: 12rpx;
  399 + padding: 20rpx 0 8rpx;
  400 +}
  401 +.sec-bar {
  402 + width: 6rpx;
  403 + height: 28rpx;
  404 + background-color: #2563EB;
  405 + border-radius: 3rpx;
  406 +}
  407 +.sec-title {
  408 + font-size: 30rpx;
  409 + font-weight: 500;
  410 + color: #1F2937;
  411 +}
  412 +
  413 +// 表单行:上下 24rpx(左右由卡片内边距控制)
  414 +.form-card :deep(.u-form-item__body) {
  415 + padding: 24rpx 0 !important;
  416 +}
  417 +.form-card :deep(.u-form-item__body__left__content__label) {
  418 + font-size: 28rpx;
  419 + color: #333333;
  420 +}
  421 +.form-card :deep(.u-line) {
  422 + background-color: #EEF1F6;
  423 +}
  424 +.form-card :deep(.u-textarea) {
  425 + padding: 16rpx;
  426 + background-color: #F5F7FA;
  427 + border-radius: 8rpx;
363 428 }
364 429 </style>
365 430 \ No newline at end of file
... ...
pages-sub/problem/regional-order-manage/distribution-order.vue
1 1 <template>
2 2 <view class="page-container">
3   - <view class="work-order-form-content commonPageLRpadding">
  3 + <view class="work-order-form-content">
4 4 <up-form label-position="left" :model="workOrderForm" ref="workOrderFormRef" labelWidth="200rpx">
  5 + <!-- 报单信息 -->
  6 + <view class="form-card">
  7 + <view class="sec-head">
  8 + <view class="sec-bar"></view>
  9 + <view class="sec-title">报单信息</view>
  10 + </view>
  11 +
5 12 <!-- 1. 工单位置(地图选择)【赋值回显 + 完全禁止修改】 -->
6   - <up-form-item label="工单位置" prop="workLocation" border-bottom required>
  13 + <up-form-item label="工单位置" prop="workLocation" border-bottom required class="form-item">
7 14 <up-input v-model="workOrderForm.workLocation" border="none" disabled placeholder="暂无工单位置"></up-input>
8 15 </up-form-item>
9 16  
10 17 <!-- 2. 问题类型(下拉框)【赋值回显 + 完全禁止修改】 -->
11   - <up-form-item label="问题类型" prop="orderName" border-bottom required>
  18 + <up-form-item label="问题类型" prop="orderName" border-bottom required class="form-item">
12 19 <up-input v-model="workOrderForm.orderName" disabled placeholder="暂无问题类型" border="none"></up-input>
13 20 </up-form-item>
14 21  
15 22 <!-- 3. 情况描述(文本域)【赋值回显 + 完全禁止修改】 -->
16   - <up-form-item label="情况描述" prop="problemDesc" required>
  23 + <up-form-item label="情况描述" prop="problemDesc" required class="form-item">
17 24 <up-textarea v-model.trim="workOrderForm.problemDesc" count maxlength="200" rows="4" disabled
18 25 disabled-color="#333333" placeholder="暂无情况描述"></up-textarea>
19 26 </up-form-item>
  27 + </view>
20 28  
21   - <!-- 4. 问题照片【赋值回显 + 完全禁止修改/删除/新增】 -->
22   - <up-form-item label="问题照片" prop="problemImgs" required>
23   - <up-upload :file-list="problemImgs.imgList.value || []" disabled multiple :width="70" :height="70"
24   - :max-count="problemImgs.uploadConfig.maxCount" :upload-text="problemImgs.uploadConfig.uploadText"
25   - :size-type="problemImgs.uploadConfig.sizeType"></up-upload>
26   - </up-form-item>
  29 + <!-- 问题照片【赋值回显 + 完全禁止修改/删除/新增】 -->
  30 + <view class="form-card">
  31 + <view class="sec-head">
  32 + <view class="sec-bar"></view>
  33 + <view class="sec-title">问题照片</view>
  34 + </view>
  35 + <up-form-item label="问题照片" prop="problemImgs" required class="form-item">
  36 + <up-upload :file-list="problemImgs.imgList.value || []" disabled multiple :width="70" :height="70"
  37 + :max-count="problemImgs.uploadConfig.maxCount" :upload-text="problemImgs.uploadConfig.uploadText"
  38 + :size-type="problemImgs.uploadConfig.sizeType"></up-upload>
  39 + </up-form-item>
  40 + </view>
27 41  
28   - <!-- 派单情况分组(放在问题照片下方,增加间距) -->
29   - <view class="dispatch-group">
30   - <view class="dispatch-title">派单情况</view>
  42 + <!-- 派单情况分组 -->
  43 + <view class="form-card">
  44 + <view class="sec-head">
  45 + <view class="sec-bar"></view>
  46 + <view class="sec-title">派单信息</view>
  47 + </view>
31 48  
32 49 <!-- 业务线单选框 -->
33   - <up-form-item label="业务线" prop="busiLineCn" border-bottom required>
  50 + <up-form-item label="业务线" prop="busiLineCn" border-bottom required class="form-item">
34 51 <up-radio-group v-model="workOrderForm.busiLineCn" placement="row" @change="handleBusiLineChange">
35 52 <up-radio v-for="item in busiLineOptions" :key="item.name" :label="item.name"
36 53 :name="item.name"></up-radio>
... ... @@ -38,7 +55,7 @@
38 55 </up-form-item>
39 56  
40 57 <!-- 道路名称(下拉框) -->
41   - <up-form-item label="道路名称" prop="roadName" border-bottom required
  58 + <up-form-item label="道路名称" prop="roadName" border-bottom required class="form-item"
42 59 @click="handleActionSheetOpen('roadName'); hideKeyboard()">
43 60 <up-input v-model="workOrderForm.roadName" readonly disabled-color="#ffffff" placeholder="请先选择工单位置"
44 61 border="none"></up-input>
... ... @@ -48,7 +65,7 @@
48 65 </up-form-item>
49 66  
50 67 <!-- 紧急程度选择 -->
51   - <up-form-item label="紧急程度" prop="pressingTypeName" border-bottom required
  68 + <up-form-item label="紧急程度" prop="pressingTypeName" border-bottom required class="form-item"
52 69 @click="handleActionSheetOpen('pressingType'); hideKeyboard()">
53 70 <up-input v-model="workOrderForm.pressingTypeName" disabled disabled-color="#ffffff" placeholder="请选择紧急程度"
54 71 border="none"></up-input>
... ... @@ -56,18 +73,19 @@
56 73 <up-icon name="arrow-right" size="16"></up-icon>
57 74 </template>
58 75 </up-form-item>
59   - </view>
60 76  
61   - <!-- 5. 完成时间 -->
62   - <up-form-item label="希望完成时间" prop="expectedFinishDate" @click="show = true; hideKeyboard()">
63   - <up-input v-model="workOrderForm.expectedFinishDate" border="none" readonly placeholder="点击选择时间"></up-input>
64   - <template #right>
65   - <view v-if="workOrderForm.expectedFinishDate" @click.stop>
66   - <up-icon name="close" size="16" @click.stop="clearExpectedFinishDate"></up-icon>
67   - </view>
68   - <up-icon name="arrow-right" size="16" v-else></up-icon>
69   - </template>
70   - </up-form-item>
  77 + <!-- 5. 完成时间 -->
  78 + <up-form-item label="希望完成时间" prop="expectedFinishDate" class="form-item"
  79 + @click="show = true; hideKeyboard()">
  80 + <up-input v-model="workOrderForm.expectedFinishDate" border="none" readonly placeholder="点击选择时间"></up-input>
  81 + <template #right>
  82 + <view v-if="workOrderForm.expectedFinishDate" @click.stop>
  83 + <up-icon name="close" size="16" @click.stop="clearExpectedFinishDate"></up-icon>
  84 + </view>
  85 + <up-icon name="arrow-right" size="16" v-else></up-icon>
  86 + </template>
  87 + </up-form-item>
  88 + </view>
71 89 </up-form>
72 90 </view>
73 91  
... ... @@ -516,28 +534,65 @@ const submitWorkOrder = async () =&gt; {
516 534 </script>
517 535  
518 536 <style lang="scss" scoped>
519   -// 全局页面样式
  537 +/* 统一卡片样式(与工单表单页一致) */
520 538 .page-container {
521 539 min-height: 100vh;
522   - padding-bottom: 100rpx; // 给底部按钮留空间
  540 + padding-bottom: 200rpx; // 给底部按钮留空间
  541 + background-color: #F4F6FA;
  542 + box-sizing: border-box;
523 543 }
524 544  
525   -// 工单表单内容容器
526 545 .work-order-form-content {
527   - background: #fff;
  546 + padding: 0 24rpx;
  547 + background: transparent;
  548 +}
  549 +
  550 +.form-item {
  551 + margin-bottom: 0;
  552 +}
  553 +
  554 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  555 +.form-card {
  556 + margin-top: 24rpx;
  557 + padding: 8rpx 24rpx;
  558 + background-color: #ffffff;
  559 + border-radius: 16rpx;
  560 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
528 561 }
529 562  
530   -// 派单情况分组样式(核心:增加顶部间距)
531   -.dispatch-group {
532   - padding-top: 20rpx; // 分组内顶部内边距,增强视觉区分
  563 +// 区块标题:蓝色竖条 + 标题文字
  564 +.sec-head {
  565 + display: flex;
  566 + align-items: center;
  567 + gap: 12rpx;
  568 + padding: 20rpx 0 8rpx;
  569 +}
  570 +.sec-bar {
  571 + width: 6rpx;
  572 + height: 28rpx;
  573 + background-color: #2563EB;
  574 + border-radius: 3rpx;
  575 +}
  576 +.sec-title {
  577 + font-size: 30rpx;
  578 + font-weight: 500;
  579 + color: #1F2937;
533 580 }
534 581  
535   -// 派单情况标题样式
536   -.dispatch-title {
537   - font-size: 32rpx;
538   - font-weight: 600;
539   - color: $u-primary;
540   - margin-bottom: 20rpx;
541   - padding-left: 10rpx;
  582 +// 表单行:上下 24rpx(左右由卡片内边距控制)
  583 +.form-card :deep(.u-form-item__body) {
  584 + padding: 24rpx 0 !important;
  585 +}
  586 +.form-card :deep(.u-form-item__body__left__content__label) {
  587 + font-size: 28rpx;
  588 + color: #333333;
  589 +}
  590 +.form-card :deep(.u-line) {
  591 + background-color: #EEF1F6;
  592 +}
  593 +.form-card :deep(.u-textarea) {
  594 + padding: 16rpx;
  595 + background-color: #F5F7FA;
  596 + border-radius: 8rpx;
542 597 }
543 598 </style>
544 599 \ No newline at end of file
... ...
pages-sub/problem/regional-order-manage/index.vue
... ... @@ -6,8 +6,8 @@
6 6 <up-tabs
7 7 v-model="activeTab"
8 8 :list="tabList"
9   - active-color="#1989fa"
10   - inactive-color="#666"
  9 + active-color="#2563EB"
  10 + inactive-color="#606266"
11 11 font-size="30rpx"
12 12 @click="handleTabChange"
13 13 />
... ... @@ -107,15 +107,16 @@
107 107 </view>
108 108  
109 109 <!-- 待办工单(0):已配置工作流动作时按配置逐个渲染按钮,点击直接执行对应动作 -->
110   - <view v-if="activeTab === 0" class="u-body-item task-btn-row mt-20">
  110 + <view v-if="activeTab === 0" class="u-body-item task-btn-row mt-20"
  111 + :style="{'--cols': getActionRowCols(actionBtnCount(item))}">
111 112 <template v-if="hasConfiguredActions(item)">
112 113 <view
113 114 v-for="action in item.configuredActions"
114 115 :key="action.code"
115   - :class="['task-btn', 'task-btn--' + getActionButtonType(action.code)]"
  116 + :class="['task-btn', 'task-btn--' + getActionButtonType(action.code, action.name)]"
116 117 @click.stop="handleUnifiedProcess(item, action)"
117 118 >{{ action.name }}</view>
118   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  119 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
119 120 </template>
120 121 <!-- 未配置:沿用原有节点按钮 -->
121 122 <template v-else>
... ... @@ -125,7 +126,7 @@
125 126 @click.stop="handleRenew(item)">重新提交</view>
126 127 <view class="task-btn task-btn--primary"
127 128 @click.stop="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</view>
128   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  129 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
129 130 </template>
130 131 </view>
131 132  
... ... @@ -241,7 +242,7 @@ import {
241 242 } from '@/api/regional-order-manage/regional-order-manage'
242 243 import { getTaskActions } from '@/api/work-order-manage/work-order-manage'
243 244 import { useUserStore } from '@/pinia/user';
244   -import { nextStepMap, buzStatusMap, getActionButtonType, toWorkerImplementPage } from '@/common/utils/common'
  245 +import { nextStepMap, buzStatusMap, getActionButtonType, getActionRowCols, toWorkerImplementPage } from '@/common/utils/common'
245 246 import { useUploadImgs } from '@/common/utils/useUploadImgs'
246 247  
247 248 // ========== 全局实例 & 常量 ==========
... ... @@ -491,6 +492,17 @@ const getProcessButtonText = (item) =&gt; {
491 492 const hasConfiguredActions = (item) =>
492 493 Array.isArray(item?.configuredActions) && item.configuredActions.length > 0
493 494  
  495 +/** 操作按钮行按钮数量:单个占一半宽度,多个等分,最多 5 个一行 */
  496 +const actionBtnCount = (item) => {
  497 + if (hasConfiguredActions(item)) {
  498 + return item.configuredActions.length + 1 // 配置动作 + 详情
  499 + }
  500 + let count = 2 // 主按钮 + 详情
  501 + if (showRejectButton(item)) count++
  502 + if (nextStepMap[item.taskKey]?.renewShow) count++
  503 + return count
  504 +}
  505 +
494 506 /** 待办-处理工单:已配置统一动作时直接执行点击的配置动作,否则回退原有处理 */
495 507 const handleUnifiedProcess = async (item, action = null) => {
496 508 const actions = Array.isArray(item?.configuredActions)
... ... @@ -576,7 +588,6 @@ const handleProcess = async (item) =&gt; {
576 588 });
577 589 }
578 590  
579   -
580 591 // 验收弹窗
581 592 else if (['巡查员验收', '养护组长验收'].includes(stepName)) {
582 593 currentAcceptItem.value = item;
... ... @@ -702,7 +713,7 @@ onLoad(() =&gt; {
702 713 <style scoped lang="scss">
703 714 .page-container {
704 715 min-height: 100vh;
705   - background-color: #fafafa;
  716 + background-color: #F4F6FA;
706 717 }
707 718  
708 719 // 顶部固定区域
... ... @@ -732,24 +743,27 @@ onLoad(() =&gt; {
732 743 }
733 744  
734 745 // 工单列表样式
  746 +// 顶部留白 = 吸顶筛选条高度(Tabs 44 + 搜索条 10+32+10 = 96px) + 12px 间距
  747 +// 原写法用 calc(var(--status-bar-height) + 140rpx),状态栏高度随机型变化,低状态栏机型会压到卡片
735 748 .common-card-list {
736   - padding: calc(var(--status-bar-height) + 140rpx) 0 30rpx;
  749 + padding: 216rpx 0 180rpx;
737 750 box-sizing: border-box;
738 751 }
739 752  
740 753 // 工单卡片样式
741 754 .order-card {
742   - margin: 0 20rpx 20rpx;
743   - background: #fff;
744   - border-radius: 12rpx;
745   - box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
  755 + margin: 0 24rpx 24rpx;
  756 + background-color: #ffffff;
  757 + border-radius: 16rpx;
  758 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
746 759 }
747 760  
748   -// 卡片操作按钮:自动换行、右对齐,动作多时每行 3~4 个,不再整行铺满
  761 +// 卡片操作按钮:单个占页面一半宽度(左对齐),多个等分,每行最多 5 个,超出自动换行
749 762 .task-btn-row {
750   - display: flex;
751   - flex-wrap: wrap;
752   - justify-content: flex-end;
  763 + display: grid;
  764 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  765 + column-gap: 12rpx;
  766 + row-gap: 10rpx;
753 767 margin-bottom: -10rpx;
754 768 }
755 769  
... ... @@ -757,20 +771,31 @@ onLoad(() =&gt; {
757 771 box-sizing: border-box;
758 772 height: 56rpx;
759 773 line-height: 56rpx;
760   - padding: 0 24rpx;
761   - margin: 0 0 10rpx 12rpx;
  774 + padding: 0 12rpx;
762 775 border-radius: 8rpx;
763 776 font-size: 24rpx;
764 777 color: #fff;
  778 + text-align: center;
765 779 white-space: nowrap;
  780 + overflow: hidden;
  781 + text-overflow: ellipsis;
766 782 }
767 783  
  784 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
768 785 .task-btn--primary {
769   - background-color: #3c9cff;
  786 + background-color: #3B9DFF;
  787 +}
  788 +
  789 +.task-btn--assign {
  790 + background-color: #2563EB;
  791 +}
  792 +
  793 +.task-btn--transfer {
  794 + background-color: #0891B2;
770 795 }
771 796  
772 797 .task-btn--success {
773   - background-color: #5ac725;
  798 + background-color: #078d0a;
774 799 }
775 800  
776 801 .task-btn--warning {
... ... @@ -785,7 +810,6 @@ onLoad(() =&gt; {
785 810 background-color: #909399;
786 811 }
787 812  
788   -
789 813 // 新增样式:解决按钮和文字间距、排版问题
790 814 .flex-1 { flex: 1; }
791 815 .text-right { text-align: right; }
... ... @@ -801,7 +825,7 @@ onLoad(() =&gt; {
801 825 .upload-wrap {
802 826 .upload-title {
803 827 font-size: 28rpx;
804   - color: #333;
  828 + color: #1a1a1a;
805 829 margin-bottom: 10rpx;
806 830 }
807 831 }
... ...
pages-sub/problem/regional-order-manage/list-detail.vue
... ... @@ -5,7 +5,7 @@
5 5 v-if="loading"
6 6 :loading="true"
7 7 title="加载中..."
8   - color="#3c9cff"
  8 + color="#2563EB"
9 9 ></up-loading-page>
10 10  
11 11 <view v-else class="main-content" :class="'pb-rows-' + actionBarRows">
... ... @@ -16,8 +16,8 @@
16 16 :list="topTabList"
17 17 :scrollable="false"
18 18 sticky
19   - active-color="#3c9cff"
20   - inactive-color="#666"
  19 + active-color="#2563EB"
  20 + inactive-color="#606266"
21 21 class="top-tabs"
22 22 @click="activeTopTabClick"
23 23 ></up-tabs>
... ... @@ -141,8 +141,8 @@
141 141 v-model="activeImgTab"
142 142 :list="imgTabList"
143 143 :scrollable="false"
144   - active-color="#3c9cff"
145   - inactive-color="#666"
  144 + active-color="#2563EB"
  145 + inactive-color="#606266"
146 146 class="img-tabs"
147 147 ></up-tabs>
148 148 <view class="img-tab-content">
... ... @@ -166,8 +166,8 @@
166 166 :list="processData.activityNodes"
167 167 :current="getCurrentStepIndex()"
168 168 direction="column"
169   - active-color="#3c9cff"
170   - inactive-color="#999"
  169 + active-color="#2563EB"
  170 + inactive-color="#909399"
171 171 class="vertical-steps"
172 172 >
173 173 <template>
... ... @@ -178,7 +178,7 @@
178 178 <template #content>
179 179 <view class="step-content-wrap">
180 180 <view class="step-title">
181   - {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }}
  181 + {{ item.name }}
182 182 </view>
183 183 <view class="step-desc">
184 184 <view class="operator-name up-line-1" v-if="item.tasks">
... ... @@ -225,17 +225,18 @@
225 225 <!-- 底部操作按钮 -->
226 226 <view v-if="activeTab === '0' && (configuredActions || nextStepMap[orderDetail.taskKey])"
227 227 class="fixed-bottom-btn-wrap order-action-bar">
228   - <!-- 已配置工作流动作:每行最多 3 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
229   - <view v-if="hasConfiguredActions" class="order-action-row">
  228 + <!-- 已配置工作流动作:每行最多 5 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
  229 + <view v-if="hasConfiguredActions" class="order-action-row"
  230 + :style="{'--cols': getActionRowCols(configuredActions.length)}">
230 231 <view
231 232 v-for="action in configuredActions"
232 233 :key="action.code"
233   - :class="['order-action-btn', 'order-action-btn--' + getActionButtonType(action.code)]"
  234 + :class="['order-action-btn', 'order-action-btn--' + getActionButtonType(action.code, action.name)]"
234 235 @click.stop="handleUnifiedProcess(orderDetail, action)"
235 236 >{{ action.name }}</view>
236 237 </view>
237   - <!-- 未配置:沿用原有节点按钮(整行展示) -->
238   - <view v-else class="order-action-row order-action-row--single">
  238 + <!-- 未配置:沿用原有节点按钮 -->
  239 + <view v-else class="order-action-row" :style="{'--cols': getActionRowCols(legacyActionCount)}">
239 240 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning"
240 241 @click.stop="handleUnifiedReject(orderDetail)">回退</view>
241 242 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success"
... ... @@ -337,7 +338,7 @@ import { timeFormat } from &#39;@/uni_modules/uview-plus&#39;
337 338 import { getApprovalDetail,workOrderDetailByID } from '@/api/regional-order-manage/regional-order-manage'
338 339 import { getTaskActions } from '@/api/work-order-manage/work-order-manage'
339 340  
340   -import { nextStepMap, calculateFormatTimeDiff, getActionButtonType, toWorkerImplementPage } from '@/common/utils/common'
  341 +import { nextStepMap, calculateFormatTimeDiff, getActionButtonType, getActionRowCols, toWorkerImplementPage } from '@/common/utils/common'
341 342 import { useUploadImgs } from '@/common/utils/useUploadImgs'
342 343 import { useUserStore } from '@/pinia/user'
343 344  
... ... @@ -523,15 +524,20 @@ const showRejectButton = computed(() =&gt; {
523 524 const hasConfiguredActions = computed(() =>
524 525 Array.isArray(configuredActions.value) && configuredActions.value.length > 0)
525 526  
  527 +/** 未配置统一动作时的按钮个数(与模板渲染顺序一致) */
  528 +const legacyActionCount = computed(() => {
  529 + let count = 1
  530 + if (showRejectButton.value) count++
  531 + if (nextStepMap[orderDetail.value.taskKey]?.renewShow) count++
  532 + return count
  533 +})
  534 +
526 535 /** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容 */
527 536 const actionBarRows = computed(() => {
528 537 if (hasConfiguredActions.value) {
529   - return Math.ceil(configuredActions.value.length / 3)
  538 + return Math.ceil(configuredActions.value.length / 5)
530 539 }
531   - let rows = 1
532   - if (showRejectButton.value) rows++
533   - if (nextStepMap[orderDetail.value.taskKey]?.renewShow) rows++
534   - return rows
  540 + return 1
535 541 })
536 542  
537 543 /** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
... ... @@ -924,33 +930,47 @@ onLoad((options: any) =&gt; {
924 930 <style scoped lang="scss">
925 931 .page-container {
926 932 min-height: 100vh;
927   - background-color: #f5f5f5;
  933 + background-color: #F4F6FA;
  934 + box-sizing: border-box;
928 935 }
929 936  
930 937 .main-content {
931 938 padding-bottom: 80rpx;
932 939 }
933 940  
  941 +/* 内容区左右留白 24rpx(设计稿 .body) */
  942 +.tab-content {
  943 + padding: 0 24rpx;
  944 + box-sizing: border-box;
  945 +}
  946 +
934 947 .detail-content {
935 948 .detail-cell-group {
936   - background-color: #fff;
937   - margin-bottom: 20rpx;
  949 + background-color: #ffffff;
  950 + border-radius: 16rpx;
  951 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  952 + overflow: hidden;
  953 + margin: 24rpx 0;
938 954 }
939 955 .empty-text {
940   - color: #999;
941   - font-size: 26rpx;
  956 + color: #909399;
  957 + font-size: 28rpx;
942 958 }
943 959 }
944 960  
945 961 .img-tabs-block {
946   - background-color: #fff;
  962 + background-color: #ffffff;
  963 + border-radius: 16rpx;
  964 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  965 + overflow: hidden;
  966 + margin-bottom: 24rpx;
947 967 .img-tab-content {
948 968 padding: 20rpx 15px;
949 969 text-align: center;
950 970 .empty-img-text {
951 971 height: 75px;
952 972 line-height: 75px;
953   - color: #999;
  973 + color: #909399;
954 974 font-size: 28rpx;
955 975 }
956 976 }
... ... @@ -961,9 +981,11 @@ onLoad((options: any) =&gt; {
961 981 margin-top: 100rpx;
962 982 }
963 983 .vertical-steps {
964   - background-color: #fff;
965   - padding: 20rpx;
966   - border-radius: 12rpx;
  984 + background-color: #ffffff;
  985 + margin: 24rpx 0;
  986 + padding: 24rpx;
  987 + border-radius: 16rpx;
  988 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
967 989 display: flex;
968 990 flex-direction: column;
969 991 gap: 20rpx;
... ... @@ -974,12 +996,12 @@ onLoad((options: any) =&gt; {
974 996 .step-title {
975 997 font-size: 30rpx;
976 998 font-weight: 600;
977   - color: #333;
  999 + color: #1a1a1a;
978 1000 margin-bottom: 12rpx;
979 1001 }
980 1002 .step-desc {
981 1003 font-size: 24rpx;
982   - color: #666;
  1004 + color: #606266;
983 1005 line-height: 1.6;
984 1006 .processing-tag {
985 1007 color: #f59c26;
... ... @@ -1001,8 +1023,8 @@ onLoad((options: any) =&gt; {
1001 1023 }
1002 1024  
1003 1025 .upload-title {
1004   - font-size: 26rpx;
1005   - color: #666;
  1026 + font-size: 28rpx;
  1027 + color: #606266;
1006 1028 margin-bottom: 10rpx;
1007 1029 }
1008 1030  
... ... @@ -1025,8 +1047,7 @@ onLoad((options: any) =&gt; {
1025 1047 height: 70px !important;
1026 1048 }
1027 1049  
1028   -// 底部动作按钮:动作多时自动换行
1029   -// 底部操作栏:白底 + 顶部投影,按钮每行最多 3 个,避免多动作时整屏遮挡工单详情
  1050 +// 底部操作栏:白底 + 顶部投影,按钮每行最多 5 个,避免多动作时整屏遮挡工单详情
1030 1051 .order-action-bar {
1031 1052 background-color: #fff;
1032 1053 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
... ... @@ -1035,21 +1056,20 @@ onLoad((options: any) =&gt; {
1035 1056 padding-bottom: calc(10rpx + env(safe-area-inset-bottom));
1036 1057 }
1037 1058  
  1059 +// 底部操作按钮:单按钮占一半宽度,多个按钮等分,每行最多 5 个
1038 1060 .order-action-row {
1039   - display: flex;
1040   - flex-wrap: wrap;
1041   - margin: -6rpx;
  1061 + display: grid;
  1062 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  1063 + gap: 12rpx;
1042 1064 }
1043 1065  
1044 1066 .order-action-btn {
1045 1067 box-sizing: border-box;
1046   - width: calc((100% - 36rpx) / 3);
1047 1068 height: 68rpx;
1048 1069 line-height: 68rpx;
1049   - margin: 6rpx;
1050 1070 padding: 0 8rpx;
1051 1071 border-radius: 8rpx;
1052   - font-size: 26rpx;
  1072 + font-size: 28rpx;
1053 1073 text-align: center;
1054 1074 color: #fff;
1055 1075 white-space: nowrap;
... ... @@ -1057,17 +1077,21 @@ onLoad((options: any) =&gt; {
1057 1077 text-overflow: ellipsis;
1058 1078 }
1059 1079  
1060   -// 未配置统一动作时按钮整行展示,保持原有观感
1061   -.order-action-row--single .order-action-btn {
1062   - width: 100%;
  1080 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
  1081 +.order-action-btn--primary {
  1082 + background-color: #3B9DFF;
1063 1083 }
1064 1084  
1065   -.order-action-btn--primary {
1066   - background-color: #3c9cff;
  1085 +.order-action-btn--assign {
  1086 + background-color: #2563EB;
  1087 +}
  1088 +
  1089 +.order-action-btn--transfer {
  1090 + background-color: #0891B2;
1067 1091 }
1068 1092  
1069 1093 .order-action-btn--success {
1070   - background-color: #5ac725;
  1094 + background-color: #078d0a;
1071 1095 }
1072 1096  
1073 1097 .order-action-btn--warning {
... ...
pages-sub/problem/regional-order-manage/list.vue
... ... @@ -478,7 +478,7 @@ onMounted(async () =&gt; {
478 478 <style scoped lang="scss">
479 479 .page-container {
480 480 min-height: 100vh;
481   - background-color: #fafafa;
  481 + background-color: #F4F6FA;
482 482 }
483 483  
484 484 .header-wrap {
... ... @@ -498,8 +498,8 @@ onMounted(async () =&gt; {
498 498 right: 0;
499 499 z-index: 99; /* 高于列表,防止被遮挡 */
500 500 background: #e4dc8e;
501   - color: #333;
502   - font-size: 26rpx;
  501 + color: #1a1a1a;
  502 + font-size: 28rpx;
503 503 padding: 14rpx 20rpx;
504 504 text-align: center;
505 505 }
... ... @@ -571,10 +571,10 @@ onMounted(async () =&gt; {
571 571 }
572 572  
573 573 .order-card {
574   - margin: 0 20rpx 20rpx;
575   - background: #fff;
576   - border-radius: 12rpx;
577   - box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
  574 + margin: 0 24rpx 24rpx;
  575 + background-color: #ffffff;
  576 + border-radius: 16rpx;
  577 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
578 578 }
579 579  
580 580 /* 工单详情按钮 贴最右侧 */
... ... @@ -593,7 +593,7 @@ onMounted(async () =&gt; {
593 593 .upload-wrap {
594 594 .upload-title {
595 595 font-size: 28rpx;
596   - color: #333;
  596 + color: #1a1a1a;
597 597 margin-bottom: 10rpx;
598 598 }
599 599 }
... ...
pages-sub/problem/regional-order-manage/order-detail.vue
... ... @@ -5,7 +5,7 @@
5 5 v-if="loading"
6 6 :loading="true"
7 7 title="加载中..."
8   - color="#3c9cff"
  8 + color="#2563EB"
9 9 ></up-loading-page>
10 10  
11 11 <!-- 主内容容器 -->
... ... @@ -17,8 +17,8 @@
17 17 :list="topTabList"
18 18 :scrollable="false"
19 19 sticky
20   - active-color="#3c9cff"
21   - inactive-color="#666"
  20 + active-color="#2563EB"
  21 + inactive-color="#606266"
22 22 class="top-tabs"
23 23 @click="activeTopTabClick"
24 24 ></up-tabs>
... ... @@ -156,8 +156,8 @@
156 156 v-model="activeImgTab"
157 157 :list="imgTabList"
158 158 :scrollable="false"
159   - active-color="#3c9cff"
160   - inactive-color="#666"
  159 + active-color="#2563EB"
  160 + inactive-color="#606266"
161 161 class="img-tabs"
162 162 ></up-tabs>
163 163  
... ... @@ -184,8 +184,8 @@
184 184 :list="processData.activityNodes"
185 185 :current="getCurrentStepIndex()"
186 186 direction="column"
187   - active-color="#3c9cff"
188   - inactive-color="#999"
  187 + active-color="#2563EB"
  188 + inactive-color="#909399"
189 189 class="vertical-steps"
190 190 >
191 191 <template>
... ... @@ -198,7 +198,7 @@
198 198 <view class="step-content-wrap">
199 199 <!-- 1. 原标题内容:节点名称 + 操作人 -->
200 200 <view class="step-title">
201   - {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }}
  201 + {{ item.name }}
202 202 </view>
203 203  
204 204 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) -->
... ... @@ -255,17 +255,18 @@
255 255 <!-- activeTab==0的时候才出现, 也就是待办 -->
256 256 <view v-if="activeTab==0&&(configuredActions||nextStepMap[orderDetail.taskKey])"
257 257 class="fixed-bottom-btn-wrap order-action-bar">
258   - <!-- 已配置工作流动作:每行最多 3 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
259   - <view v-if="hasConfiguredActions" class="order-action-row">
  258 + <!-- 已配置工作流动作:每行最多 5 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
  259 + <view v-if="hasConfiguredActions" class="order-action-row"
  260 + :style="{'--cols': getActionRowCols(configuredActions.length)}">
260 261 <view
261 262 v-for="action in configuredActions"
262 263 :key="action.code"
263   - :class="['order-action-btn', 'order-action-btn--' + getActionButtonType(action.code)]"
  264 + :class="['order-action-btn', 'order-action-btn--' + getActionButtonType(action.code, action.name)]"
264 265 @click.stop="handleUnifiedProcess(orderDetail, action)"
265 266 >{{ action.name }}</view>
266 267 </view>
267   - <!-- 未配置:沿用原有节点按钮(整行展示) -->
268   - <view v-else class="order-action-row order-action-row--single">
  268 + <!-- 未配置:沿用原有节点按钮 -->
  269 + <view v-else class="order-action-row" :style="{'--cols': getActionRowCols(legacyActionCount)}">
269 270 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning"
270 271 @click.stop="handleUnifiedReject(orderDetail)">回退</view>
271 272 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success"
... ... @@ -381,7 +382,7 @@ import {
381 382 dcyUniversalApproval,
382 383 aiUniversalApproval
383 384 } from '@/api/regional-order-manage/regional-order-manage';
384   -import {nextStepMap, buzStatusMap, calculateFormatTimeDiff, getActionButtonType, toWorkerImplementPage} from '@/common/utils/common'
  385 +import {nextStepMap, buzStatusMap, calculateFormatTimeDiff, getActionButtonType, getActionRowCols, toWorkerImplementPage} from '@/common/utils/common'
385 386 import {getTaskActions} from '@/api/work-order-manage/work-order-manage';
386 387 import {useUploadImgs} from '@/common/utils/useUploadImgs'
387 388 import { useUserStore } from '@/pinia/user';
... ... @@ -392,7 +393,6 @@ const USER_ROLES = userStore.userInfo?.roles || [];
392 393 // ========== 页面通信事件通道 解决未定义BUG ==========
393 394 const eventChannel = ref<any>(null);
394 395  
395   -
396 396 // ========== 公共封装方法 (和列表页完全一致) ==========
397 397 /**
398 398 * 统一提示方法
... ... @@ -593,15 +593,20 @@ const showRejectButton = computed(() =&gt; {
593 593 const hasConfiguredActions = computed(() =>
594 594 Array.isArray(configuredActions.value) && configuredActions.value.length > 0)
595 595  
596   -/** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容 */
  596 +/** 未配置统一动作时的按钮数量:主按钮 + 可选的回退/重新提交 */
  597 +const legacyActionCount = computed(() => {
  598 + let count = 1
  599 + if (showRejectButton.value) count++
  600 + if (nextStepMap[orderDetail.value.taskKey]?.renewShow) count++
  601 + return count
  602 +})
  603 +
  604 +/** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容(每行最多 5 个) */
597 605 const actionBarRows = computed(() => {
598 606 if (hasConfiguredActions.value) {
599   - return Math.ceil(configuredActions.value.length / 3)
  607 + return Math.ceil(configuredActions.value.length / 5)
600 608 }
601   - let rows = 1
602   - if (showRejectButton.value) rows++
603   - if (nextStepMap[orderDetail.value.taskKey]?.renewShow) rows++
604   - return rows
  609 + return 1
605 610 })
606 611  
607 612 /** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
... ... @@ -1001,6 +1006,8 @@ onShow(() =&gt; {});
1001 1006 // 全局样式
1002 1007 .page-container {
1003 1008 min-height: 100vh;
  1009 + background-color: #F4F6FA;
  1010 + box-sizing: border-box;
1004 1011 }
1005 1012  
1006 1013 // 主内容容器
... ... @@ -1012,29 +1019,39 @@ onShow(() =&gt; {});
1012 1019 .top-tabs {
1013 1020 }
1014 1021  
1015   -// Tab内容区
  1022 +// Tab内容区:左右 24rpx 留白(设计稿 .body)
1016 1023 .tab-content {
  1024 + padding: 0 24rpx;
  1025 + box-sizing: border-box;
1017 1026 }
1018 1027  
1019 1028 // 工单详情内容
1020 1029 .detail-content {
  1030 + // 白色卡片:16rpx 圆角 + 卡片阴影(设计稿 .card)
1021 1031 .detail-cell-group {
1022   - background-color: #fff;
1023   - margin-bottom: 20rpx;
  1032 + background-color: #ffffff;
  1033 + margin: 24rpx 0;
  1034 + border-radius: 16rpx;
  1035 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  1036 + overflow: hidden;
1024 1037 }
1025 1038  
1026 1039 .cell-content-wrap {
1027 1040 }
1028 1041  
1029 1042 .empty-text {
1030   - color: #999;
1031   - font-size: 26rpx;
  1043 + color: #909399;
  1044 + font-size: 28rpx;
1032 1045 }
1033 1046 }
1034 1047  
1035 1048 // 图片分类Tabs区块
1036 1049 .img-tabs-block {
1037   - background-color: #fff;
  1050 + background-color: #ffffff;
  1051 + margin-bottom: 24rpx;
  1052 + border-radius: 16rpx;
  1053 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  1054 + overflow: hidden;
1038 1055  
1039 1056 .img-tab-content {
1040 1057 padding: 20rpx 15px ;
... ... @@ -1046,7 +1063,7 @@ onShow(() =&gt; {});
1046 1063 .empty-img-text {
1047 1064 height: 75px;
1048 1065 line-height: 75px;
1049   - color: #999;
  1066 + color: #909399;
1050 1067 font-size: 28rpx;
1051 1068 }
1052 1069 }
... ... @@ -1059,9 +1076,11 @@ onShow(() =&gt; {});
1059 1076 }
1060 1077  
1061 1078 .vertical-steps {
1062   - background-color: #fff;
1063   - padding: 20rpx;
1064   - border-radius: 12rpx;
  1079 + background-color: #ffffff;
  1080 + margin: 24rpx 0;
  1081 + padding: 24rpx;
  1082 + border-radius: 16rpx;
  1083 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
1065 1084 display: flex;
1066 1085 flex-direction: column;
1067 1086 gap: 20rpx;
... ... @@ -1074,20 +1093,20 @@ onShow(() =&gt; {});
1074 1093 .step-title {
1075 1094 font-size: 30rpx;
1076 1095 font-weight: 600;
1077   - color: #333;
  1096 + color: #1a1a1a;
1078 1097 margin-bottom: 12rpx;
1079 1098  
1080 1099 .operator-name {
1081 1100 font-size: 30rpx;
1082 1101 font-weight: 600;
1083   - color: #333;
  1102 + color: #1a1a1a;
1084 1103 margin-left: 20rpx;
1085 1104 }
1086 1105 }
1087 1106  
1088 1107 .step-desc {
1089 1108 font-size: 24rpx;
1090   - color: #666;
  1109 + color: #606266;
1091 1110 line-height: 1.6;
1092 1111 margin-bottom: 12rpx;
1093 1112  
... ... @@ -1111,7 +1130,7 @@ onShow(() =&gt; {});
1111 1130  
1112 1131 .no-img-tip {
1113 1132 font-size: 24rpx;
1114   - color: #999;
  1133 + color: #909399;
1115 1134 margin-top: 10rpx;
1116 1135 }
1117 1136 }
... ... @@ -1124,7 +1143,7 @@ onShow(() =&gt; {});
1124 1143  
1125 1144 .upload-title {
1126 1145 font-size: 28rpx;
1127   - color: #333;
  1146 + color: #1a1a1a;
1128 1147 margin-bottom: 10rpx;
1129 1148 }
1130 1149 }
... ... @@ -1173,7 +1192,7 @@ onShow(() =&gt; {});
1173 1192 }
1174 1193  
1175 1194 // 底部动作按钮:动作多时自动换行
1176   -// 底部操作栏:白底 + 顶部投影,按钮每行最多 3 个,避免多动作时整屏遮挡工单详情
  1195 +// 底部操作栏:白底 + 顶部投影,按钮每行最多 5 个,避免多动作时整屏遮挡工单详情
1177 1196 .order-action-bar {
1178 1197 background-color: #fff;
1179 1198 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
... ... @@ -1183,20 +1202,19 @@ onShow(() =&gt; {});
1183 1202 }
1184 1203  
1185 1204 .order-action-row {
1186   - display: flex;
1187   - flex-wrap: wrap;
1188   - margin: -6rpx;
  1205 + display: grid;
  1206 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  1207 + column-gap: 12rpx;
  1208 + row-gap: 12rpx;
1189 1209 }
1190 1210  
1191 1211 .order-action-btn {
1192 1212 box-sizing: border-box;
1193   - width: calc((100% - 36rpx) / 3);
1194 1213 height: 68rpx;
1195 1214 line-height: 68rpx;
1196   - margin: 6rpx;
1197 1215 padding: 0 8rpx;
1198 1216 border-radius: 8rpx;
1199   - font-size: 26rpx;
  1217 + font-size: 28rpx;
1200 1218 text-align: center;
1201 1219 color: #fff;
1202 1220 white-space: nowrap;
... ... @@ -1204,17 +1222,21 @@ onShow(() =&gt; {});
1204 1222 text-overflow: ellipsis;
1205 1223 }
1206 1224  
1207   -// 未配置统一动作时按钮整行展示,保持原有观感
1208   -.order-action-row--single .order-action-btn {
1209   - width: 100%;
  1225 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
  1226 +.order-action-btn--primary {
  1227 + background-color: #3B9DFF;
1210 1228 }
1211 1229  
1212   -.order-action-btn--primary {
1213   - background-color: #3c9cff;
  1230 +.order-action-btn--assign {
  1231 + background-color: #2563EB;
  1232 +}
  1233 +
  1234 +.order-action-btn--transfer {
  1235 + background-color: #0891B2;
1214 1236 }
1215 1237  
1216 1238 .order-action-btn--success {
1217   - background-color: #5ac725;
  1239 + background-color: #078d0a;
1218 1240 }
1219 1241  
1220 1242 .order-action-btn--warning {
... ...
pages-sub/problem/work-order-manage/add-maintain-order.vue
1 1 <template>
2 2 <view class="page-container">
  3 + <!-- 顶部信息条:工单编号(设计稿 .banner) -->
  4 + <view class="order-banner">
  5 + <view class="banner-icon">i</view>
  6 + <view class="banner-text">工单编号:{{ workOrderForm.orderNo || '--' }}</view>
  7 + </view>
3 8 <view class="work-order-form-content commonPageLRpadding">
4 9 <up-form
5 10 label-position="left"
... ... @@ -7,6 +12,12 @@
7 12 ref="workOrderFormRef"
8 13 labelWidth="170rpx"
9 14 >
  15 + <!-- ========== 工单信息(设计稿 .card) ========== -->
  16 + <view class="form-card form-card--info">
  17 + <view class="sec-head">
  18 + <view class="sec-bar"></view>
  19 + <view class="sec-title">工单信息</view>
  20 + </view>
10 21 <!-- 1. 工单编号(只读展示,从缓存获取) -->
11 22 <up-form-item
12 23 label="工单编号"
... ... @@ -59,7 +70,14 @@
59 70 </template>
60 71 </up-form-item>
61 72  
62   - <!-- 3. 处理建议(处理情况描述,必填) -->
  73 + </view>
  74 +
  75 + <!-- ========== 处理情况(设计稿 .card) ========== -->
  76 + <view class="form-card">
  77 + <view class="sec-head">
  78 + <view class="sec-bar"></view>
  79 + <view class="sec-title">处理情况</view>
  80 + </view>
63 81 <up-form-item
64 82 label="处理情况"
65 83 prop="reason"
... ... @@ -74,10 +92,14 @@
74 92 @blur="() => workOrderFormRef.validateField('reason')"
75 93 ></up-textarea>
76 94 </up-form-item>
  95 + </view>
77 96  
78 97 <!-- 4. 动态字段:按「业务类型(busiLine) + 作业类型」加载数据中心配置的工单填报项 -->
79   - <view class="dynamic-field-block" v-if="workOrderForm.workTypeId">
80   - <view class="dynamic-field-title">作业填报</view>
  98 + <view class="form-card" v-if="workOrderForm.workTypeId">
  99 + <view class="sec-head">
  100 + <view class="sec-bar"></view>
  101 + <view class="sec-title">作业填报</view>
  102 + </view>
81 103 <work-field-form
82 104 ref="workFieldFormRef"
83 105 :business-type="workOrderForm.businessType"
... ... @@ -90,13 +112,19 @@
90 112 </view>
91 113 </view>
92 114  
  115 + <!-- ========== 上传图片(设计稿 .card) ========== -->
  116 + <view class="form-card">
  117 + <view class="sec-head">
  118 + <view class="sec-bar"></view>
  119 + <view class="sec-title">上传图片</view>
  120 + </view>
93 121 <!-- Tabs标签栏(图片切换:开始、进行中、结束、人员、材料)- 改造后 -->
94   - <view class="tabs-wrap " style="margin-top: 30rpx;">
  122 + <view class="tabs-wrap">
95 123 <up-tabs
96 124 v-model="activeTab"
97 125 :list="tabList"
98 126 line-width="40rpx"
99   - active-color="#1989fa"
  127 + active-color="#2563EB"
100 128 inactive-color="#666666"
101 129 @change = "imgTabChange"
102 130  
... ... @@ -110,7 +138,7 @@
110 138 </view>
111 139 </template>
112 140 </up-tabs>
113   - <view class="tab-content" style="padding-top: 20rpx; background: #fff; padding-bottom: 20rpx;">
  141 + <view class="tab-content">
114 142 <!-- 开始阶段图片上传 -->
115 143 <view v-if="activeTab == 0">
116 144 <up-form-item prop="startImgs">
... ... @@ -183,6 +211,7 @@
183 211 </view>
184 212 </view>
185 213 </view>
  214 + </view>
186 215 </up-form>
187 216 </view>
188 217  
... ... @@ -1022,16 +1051,94 @@ const submitWorkOrder = async () =&gt; {
1022 1051 </script>
1023 1052  
1024 1053 <style lang="scss" scoped>
1025   -// 页面容器样式
  1054 +// 页面容器:浅灰底 + 给底部固定栏(按钮 88rpx + 上下各 24rpx)留空间
1026 1055 .page-container {
1027 1056 min-height: 100vh;
1028   - padding-bottom: 100rpx; // 给底部按钮留空间
  1057 + padding-bottom: calc(180rpx + constant(safe-area-inset-bottom));
  1058 + padding-bottom: calc(180rpx + env(safe-area-inset-bottom));
  1059 + background-color: #F4F6FA;
  1060 +}
  1061 +
  1062 +// 顶部信息条:浅蓝底 + 蓝字 + 圆形图标(设计稿 .banner)
  1063 +.order-banner {
  1064 + display: flex;
  1065 + align-items: center;
  1066 + gap: 12rpx;
  1067 + margin: 24rpx 24rpx 0;
  1068 + padding: 16rpx 24rpx;
  1069 + background-color: #EBF3FF;
  1070 + border-radius: 16rpx;
  1071 + color: #2563EB;
  1072 + font-size: 26rpx;
  1073 + line-height: 1.5;
  1074 +
  1075 + .banner-icon {
  1076 + box-sizing: border-box;
  1077 + flex: 0 0 auto;
  1078 + width: 30rpx;
  1079 + height: 30rpx;
  1080 + line-height: 26rpx;
  1081 + text-align: center;
  1082 + font-size: 22rpx;
  1083 + font-weight: 600;
  1084 + color: #2563EB;
  1085 + border: 2rpx solid #2563EB;
  1086 + border-radius: 50%;
  1087 + }
  1088 +
  1089 + .banner-text {
  1090 + flex: 1;
  1091 + min-width: 0;
  1092 + word-break: break-all;
  1093 + }
1029 1094 }
1030 1095  
1031   -// 表单内容容器
  1096 +// 表单内容容器:透明底,左右 24rpx(覆盖全局 commonPageLRpadding 的 15px)
1032 1097 .work-order-form-content {
1033   - background: #fff;
1034   - padding-bottom: 30rpx;
  1098 + padding: 0 24rpx;
  1099 + background: transparent;
  1100 +}
  1101 +
  1102 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  1103 +.form-card {
  1104 + margin-top: 24rpx;
  1105 + padding: 8rpx 24rpx;
  1106 + background-color: #ffffff;
  1107 + border-radius: 16rpx;
  1108 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  1109 +}
  1110 +
  1111 +// 区块标题:蓝色竖条 + 标题文字
  1112 +.sec-head {
  1113 + display: flex;
  1114 + align-items: center;
  1115 + gap: 12rpx;
  1116 + padding: 20rpx 0 8rpx;
  1117 +}
  1118 +
  1119 +.sec-bar {
  1120 + width: 6rpx;
  1121 + height: 28rpx;
  1122 + background-color: #2563EB;
  1123 + border-radius: 3rpx;
  1124 +}
  1125 +
  1126 +.sec-title {
  1127 + font-size: 30rpx;
  1128 + font-weight: 500;
  1129 + color: #1F2937;
  1130 +}
  1131 +
  1132 +// 表单行:上下 24rpx(左右由卡片内边距控制)
  1133 +:deep(.u-form-item__body) {
  1134 + padding: 24rpx 0 !important;
  1135 +}
  1136 +
  1137 +// 工单信息卡片:输入值右对齐(只作用于静态字段,动态填报项保持原样)
  1138 +.form-card--info :deep(.u-input__content__field-wrapper__field) {
  1139 + text-align: right;
  1140 + font-size: 28rpx;
  1141 + color: #1F2937;
1035 1142 }
1036 1143  
1037 1144 // Tabs容器样式
... ... @@ -1051,23 +1158,39 @@ const submitWorkOrder = async () =&gt; {
1051 1158 font-weight: bold;
1052 1159 }
1053 1160  
1054   -// 作业填报(动态字段)区块
1055   -.dynamic-field-block {
1056   - margin-top: 10rpx;
  1161 +// 作业填报无配置项时的提示
  1162 +.dynamic-field-empty {
  1163 + padding: 30rpx 0;
  1164 + text-align: center;
  1165 + font-size: 28rpx;
  1166 + color: #909399;
  1167 +}
1057 1168  
1058   - .dynamic-field-title {
1059   - padding: 20rpx 0 10rpx;
1060   - font-size: 30rpx;
1061   - font-weight: 600;
1062   - color: #303133;
1063   - border-bottom: 1rpx solid #f0f0f0;
  1169 +// 底部固定操作栏:白底 + 上分隔线 + 蓝色渐变主按钮(设计稿 .bar / .btn.pri)
  1170 +.fixed-bottom-btn-wrap {
  1171 + position: fixed;
  1172 + left: 0;
  1173 + right: 0;
  1174 + bottom: 0;
  1175 + z-index: 10;
  1176 + padding: 24rpx 24rpx calc(24rpx + constant(safe-area-inset-bottom));
  1177 + padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
  1178 + background-color: #ffffff;
  1179 + border-top: 1rpx solid #E8EBF0;
  1180 + box-shadow: 0 -8rpx 28rpx rgba(17, 24, 39, 0.06);
  1181 +
  1182 + :deep(.u-button) {
  1183 + height: 88rpx !important;
  1184 + border-radius: 16rpx !important;
  1185 + border: none !important;
  1186 + /* 与顶部导航栏同色 */
  1187 + background-color: #2563EB !important;
  1188 + background-image: none !important;
1064 1189 }
1065 1190  
1066   - .dynamic-field-empty {
1067   - padding: 30rpx 0;
1068   - text-align: center;
1069   - font-size: 26rpx;
1070   - color: #999;
  1191 + :deep(.u-button__text) {
  1192 + font-size: 30rpx !important;
  1193 + font-weight: 500 !important;
1071 1194 }
1072 1195 }
1073 1196  
... ...
pages-sub/problem/work-order-manage/add-order.vue
1 1 <template>
2 2 <view class="page-container">
3   - <view class="work-order-form-content commonPageLRpadding">
  3 + <view class="work-order-form-content">
4 4 <up-form label-position="left" :model="workOrderForm" ref="workOrderFormRef" labelWidth="200rpx">
5   - <!-- 业务线单选框 -->
6   - <up-form-item label="业务线" prop="busiLineCn" border-bottom required>
7   - <up-radio-group v-model="workOrderForm.busiLineCn" placement="row" @change="handleBusiLineChange">
8   - <up-radio v-for="item in busiLineOptions" :key="item.name" :label="item.name" :name="item.name"></up-radio>
9   - </up-radio-group>
10   - </up-form-item>
11   - <!-- 1. 工单位置(地图选择) -->
12   - <up-form-item label="工单位置" prop="workLocation" border-bottom required
13   - @click="chooseWorkLocation(); hideKeyboard()">
14   - <up-input v-model="workOrderForm.workLocation" border="none" readonly suffix-icon="map-fill"
15   - placeholder="点击选择工单位置"></up-input>
16   - </up-form-item>
17   - <!-- 2. 道路名称(下拉框action-sheet,保留不变) -->
18   - <up-form-item label="道路名称" prop="roadName" border-bottom required
19   - @click="handleActionSheetOpen('roadName'); hideKeyboard()">
20   - <up-input v-model="workOrderForm.roadName" readonly disabled-color="#ffffff" placeholder="请先选择工单位置"
21   - border="none"></up-input>
22   - <template #right>
23   - <up-icon name="arrow-right" size="16"></up-icon>
24   - </template>
25   - </up-form-item>
26   - <!-- 3. 问题类型 级联选择器【对齐参考页面】 -->
27   - <up-form-item label="问题类型" prop="orderName" border-bottom required @click="openCascader(); hideKeyboard()">
28   - <up-input v-model="workOrderForm.orderName" disabled disabled-color="#ffffff" placeholder="请选择问题类型"
29   - border="none"></up-input>
30   - <template #right>
31   - <up-icon name="arrow-right" size="16"></up-icon>
32   - </template>
33   - </up-form-item>
34   - <!-- 新增:紧急程度选择 -->
35   - <up-form-item label="紧急程度" prop="pressingTypeName" border-bottom required
36   - @click="handleActionSheetOpen('pressingType'); hideKeyboard()">
37   - <up-input v-model="workOrderForm.pressingTypeName" disabled disabled-color="#ffffff" placeholder="请选择紧急程度"
38   - border="none"></up-input>
39   - <template #right>
40   - <up-icon name="arrow-right" size="16"></up-icon>
41   - </template>
42   - </up-form-item>
43   - <!-- 4. 情况描述(文本域) -->
44   - <up-form-item label="情况描述" prop="problemDesc" required>
45   - <up-textarea placeholder="请输入情况描述(最多200字)" v-model.trim="workOrderForm.problemDesc" count maxlength="200"
46   - rows="4" @blur="() => workOrderFormRef.value?.validateField('problemDesc')"></up-textarea>
47   - </up-form-item>
  5 + <!-- 工单信息 -->
  6 + <view class="form-card">
  7 + <view class="sec-head">
  8 + <view class="sec-bar"></view>
  9 + <view class="sec-title">工单信息</view>
  10 + </view>
  11 + <!-- 业务线单选框 -->
  12 + <up-form-item label="业务线" prop="busiLineCn" border-bottom required>
  13 + <up-radio-group v-model="workOrderForm.busiLineCn" placement="row" @change="handleBusiLineChange">
  14 + <up-radio v-for="item in busiLineOptions" :key="item.name" :label="item.name" :name="item.name"></up-radio>
  15 + </up-radio-group>
  16 + </up-form-item>
  17 + <!-- 1. 工单位置(地图选择) -->
  18 + <up-form-item label="工单位置" prop="workLocation" border-bottom required
  19 + @click="chooseWorkLocation(); hideKeyboard()">
  20 + <up-input v-model="workOrderForm.workLocation" border="none" readonly suffix-icon="map-fill"
  21 + placeholder="点击选择工单位置"></up-input>
  22 + </up-form-item>
  23 + <!-- 2. 道路名称(下拉框action-sheet,保留不变) -->
  24 + <up-form-item label="道路名称" prop="roadName" border-bottom required
  25 + @click="handleActionSheetOpen('roadName'); hideKeyboard()">
  26 + <up-input v-model="workOrderForm.roadName" readonly disabled-color="#ffffff" placeholder="请先选择工单位置"
  27 + border="none"></up-input>
  28 + <template #right>
  29 + <up-icon name="arrow-right" size="16"></up-icon>
  30 + </template>
  31 + </up-form-item>
  32 + <!-- 3. 问题类型 级联选择器【对齐参考页面】 -->
  33 + <up-form-item label="问题类型" prop="orderName" border-bottom required @click="openCascader(); hideKeyboard()">
  34 + <up-input v-model="workOrderForm.orderName" disabled disabled-color="#ffffff" placeholder="请选择问题类型"
  35 + border="none"></up-input>
  36 + <template #right>
  37 + <up-icon name="arrow-right" size="16"></up-icon>
  38 + </template>
  39 + </up-form-item>
  40 + <!-- 新增:紧急程度选择 -->
  41 + <up-form-item label="紧急程度" prop="pressingTypeName" border-bottom required
  42 + @click="handleActionSheetOpen('pressingType'); hideKeyboard()">
  43 + <up-input v-model="workOrderForm.pressingTypeName" disabled disabled-color="#ffffff" placeholder="请选择紧急程度"
  44 + border="none"></up-input>
  45 + <template #right>
  46 + <up-icon name="arrow-right" size="16"></up-icon>
  47 + </template>
  48 + </up-form-item>
  49 + </view>
  50 +
  51 + <!-- 情况描述 -->
  52 + <view class="form-card form-card--field">
  53 + <view class="sec-head">
  54 + <view class="sec-bar"></view>
  55 + <view class="sec-title">情况描述</view>
  56 + </view>
  57 + <up-form-item label="情况描述" prop="problemDesc" required>
  58 + <up-textarea placeholder="请输入情况描述(最多200字)" v-model.trim="workOrderForm.problemDesc" count maxlength="200"
  59 + rows="4" @blur="() => workOrderFormRef.value?.validateField('problemDesc')"></up-textarea>
  60 + </up-form-item>
  61 + </view>
  62 +
48 63 <!-- 问题照片 -->
49   - <up-form-item label="问题照片" prop="problemImgs" border-bottom required>
50   - <up-upload :file-list="problemImgs.imgList.value || []" @after-read="problemImgs.uploadImgs"
51   - @delete="problemImgs.deleteImg" multiple :width="70" :height="70"
52   - :max-count="problemImgs.uploadConfig.maxCount" :upload-text="problemImgs.uploadConfig.uploadText"
53   - :size-type="problemImgs.uploadConfig.sizeType"></up-upload>
54   - </up-form-item>
55   - <!-- 完成时间 -->
56   - <up-form-item label="希望完成时间" prop="expectedFinishDate" @click="show = true; hideKeyboard()">
57   - <up-input v-model="workOrderForm.expectedFinishDate" border="none" readonly placeholder="点击选择时间"></up-input>
58   - <template #right>
59   - <view v-if="workOrderForm.expectedFinishDate" @click.stop>
60   - <up-icon name="close" size="20" @click.stop="clearExpectedFinishDate"></up-icon>
61   - </view>
62   - <up-icon name="arrow-right" size="16" v-else></up-icon>
63   - </template>
64   - </up-form-item>
65   - <!-- 重点巡检区域 -->
66   - <up-form-item label="重点巡检区域" prop="keyInspection" border-bottom required>
67   - <up-radio-group v-model="workOrderForm.keyInspection" @change="groupChange">
68   - <up-radio
69   - :customStyle="{marginBottom: '8px'}"
70   - v-for="(item, index) in keyInspectionOptions"
71   - :key="index"
72   - :label="item.name"
73   - :name="item.name"
74   - >
75   - </up-radio>
76   - </up-radio-group>
77   - </up-form-item>
  64 + <view class="form-card form-card--field">
  65 + <view class="sec-head">
  66 + <view class="sec-bar"></view>
  67 + <view class="sec-title">问题照片</view>
  68 + </view>
  69 + <up-form-item label="问题照片" prop="problemImgs" required>
  70 + <up-upload :file-list="problemImgs.imgList.value || []" @after-read="problemImgs.uploadImgs"
  71 + @delete="problemImgs.deleteImg" multiple :width="70" :height="70"
  72 + :max-count="problemImgs.uploadConfig.maxCount" :upload-text="problemImgs.uploadConfig.uploadText"
  73 + :size-type="problemImgs.uploadConfig.sizeType"></up-upload>
  74 + </up-form-item>
  75 + </view>
  76 +
  77 + <!-- 其他信息 -->
  78 + <view class="form-card">
  79 + <view class="sec-head">
  80 + <view class="sec-bar"></view>
  81 + <view class="sec-title">其他信息</view>
  82 + </view>
  83 + <!-- 完成时间 -->
  84 + <up-form-item label="希望完成时间" prop="expectedFinishDate" border-bottom @click="show = true; hideKeyboard()">
  85 + <up-input v-model="workOrderForm.expectedFinishDate" border="none" readonly placeholder="点击选择时间"></up-input>
  86 + <template #right>
  87 + <view v-if="workOrderForm.expectedFinishDate" @click.stop>
  88 + <up-icon name="close" size="20" @click.stop="clearExpectedFinishDate"></up-icon>
  89 + </view>
  90 + <up-icon name="arrow-right" size="16" v-else></up-icon>
  91 + </template>
  92 + </up-form-item>
  93 + <!-- 重点巡检区域 -->
  94 + <up-form-item label="重点巡检区域" prop="keyInspection" border-bottom required>
  95 + <up-radio-group v-model="workOrderForm.keyInspection" @change="groupChange">
  96 + <up-radio
  97 + :customStyle="{marginBottom: '8px'}"
  98 + v-for="(item, index) in keyInspectionOptions"
  99 + :key="index"
  100 + :label="item.name"
  101 + :name="item.name"
  102 + >
  103 + </up-radio>
  104 + </up-radio-group>
  105 + </up-form-item>
  106 + </view>
78 107 </up-form>
79 108 </view>
80 109 <!-- 底部提交按钮 -->
81 110 <view class="fixed-bottom-btn-wrap">
82   - <up-button type="primary" text="提交工单" @click="submitWorkOrder"></up-button>
  111 + <up-button type="primary" text="提交" color="#2563EB" @click="submitWorkOrder"></up-button>
83 112 </view>
84 113 <!-- 通用下拉弹窗:道路名称、紧急程度保留 -->
85 114 <up-action-sheet :show="showActionSheet" :actions="currentActionSheetData.list"
... ... @@ -586,9 +615,104 @@ const submitWorkOrder = async () =&gt; {
586 615 <style lang="scss" scoped>
587 616 .page-container {
588 617 min-height: 100vh;
589   - padding-bottom: 100rpx;
  618 + padding-bottom: 200rpx;
  619 + background-color: #F4F6FA;
  620 + box-sizing: border-box;
590 621 }
  622 +
591 623 .work-order-form-content {
592   - background: #fff;
  624 + padding: 0 24rpx;
  625 + background: transparent;
  626 +}
  627 +
  628 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  629 +.form-card {
  630 + margin-top: 24rpx;
  631 + padding: 8rpx 24rpx;
  632 + background-color: #ffffff;
  633 + border-radius: 16rpx;
  634 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  635 +}
  636 +
  637 +// 区块标题:蓝色竖条 + 标题文字
  638 +.sec-head {
  639 + display: flex;
  640 + align-items: center;
  641 + gap: 12rpx;
  642 + padding: 20rpx 0 8rpx;
  643 +}
  644 +.sec-bar {
  645 + width: 6rpx;
  646 + height: 28rpx;
  647 + background-color: #2563EB;
  648 + border-radius: 3rpx;
  649 +}
  650 +.sec-title {
  651 + font-size: 30rpx;
  652 + font-weight: 500;
  653 + color: #1F2937;
  654 +}
  655 +
  656 +// 表单行:上下 24rpx(左右由卡片内边距控制)
  657 +.form-card :deep(.u-form-item__body) {
  658 + padding: 24rpx 0 !important;
  659 +}
  660 +.form-card :deep(.u-form-item__body__left__content__label) {
  661 + font-size: 28rpx;
  662 + color: #333333;
  663 +}
  664 +.form-card :deep(.u-line) {
  665 + background-color: #EEF1F6;
  666 +}
  667 +/* 卡片内最后一行不画分隔线 */
  668 +.form-card :deep(.u-form-item:last-child .u-line) {
  669 + display: none;
  670 +}
  671 +
  672 +/* 情况描述 / 问题照片:分区标题已说明字段,隐藏左侧标签、内容整行铺满 */
  673 +.form-card--field :deep(.u-form-item__body__left) {
  674 + display: none;
  675 +}
  676 +.form-card--field :deep(.u-form-item__body__right) {
  677 + flex: 1;
  678 +}
  679 +.form-card--field :deep(.u-form-item__body) {
  680 + padding: 16rpx 0 24rpx;
  681 +}
  682 +/* 文本域:浅灰圆角输入区 */
  683 +.form-card--field :deep(.u-textarea) {
  684 + padding: 20rpx 20rpx 4rpx;
  685 + background-color: #F5F7FA;
  686 + border-radius: 12rpx;
  687 +}
  688 +.form-card--field :deep(.u-textarea__count) {
  689 + color: #9CA3AF;
  690 +}
  691 +/* 上传:虚线框 */
  692 +.form-card--field :deep(.u-upload__button) {
  693 + background-color: #FAFBFC;
  694 + border: 1rpx dashed #C8D2E0;
  695 + border-radius: 12rpx;
  696 +}
  697 +
  698 +/* 底部提交栏 */
  699 +.fixed-bottom-btn-wrap {
  700 + position: fixed;
  701 + left: 0;
  702 + right: 0;
  703 + bottom: 0;
  704 + z-index: 999;
  705 + padding: 16rpx 24rpx;
  706 + padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
  707 + background-color: #ffffff;
  708 + box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
  709 + box-sizing: border-box;
  710 +}
  711 +.fixed-bottom-btn-wrap :deep(.u-button) {
  712 + height: 88rpx !important;
  713 + border-radius: 16rpx !important;
  714 + font-size: 30rpx !important;
  715 + /* 与顶部导航栏同色 #2563EB */
  716 + border-color: #2563EB;
593 717 }
594 718 </style>
... ...
pages-sub/problem/work-order-manage/distribution-order.vue
... ... @@ -7,52 +7,66 @@
7 7 ref="workOrderFormRef"
8 8 labelWidth="190rpx"
9 9 >
10   - <!-- 1. 工单编号(从URL获取展示) -->
11   - <up-form-item
12   - label="工单编号"
13   - border-bottom
14   - >
15   - <up-input
16   - v-model="workOrderForm.orderNo"
17   - border="none"
18   - readonly
19   - placeholder="暂无工单编号"
20   - ></up-input>
21   - </up-form-item>
  10 + <!-- ========== 工单信息(设计稿 .card) ========== -->
  11 + <view class="form-card form-card--info">
  12 + <view class="sec-head">
  13 + <view class="sec-bar"></view>
  14 + <view class="sec-title">工单信息</view>
  15 + </view>
22 16  
23   - <!-- 2. 养护员选择(必选,下拉框) -->
24   - <up-form-item
25   - label="养护员"
26   - prop="assigneeName"
27   - border-bottom
28   - required
29   - @click="handleActionSheetOpen('assignee'); hideKeyboard()"
30   - >
31   - <up-input
32   - v-model="workOrderForm.assigneeName"
33   - disabled
34   - disabled-color="#ffffff"
35   - placeholder="请选择养护员"
36   - border="none"
37   - ></up-input>
38   - <template #right>
39   - <up-icon name="arrow-right" size="16"></up-icon>
40   - </template>
41   - </up-form-item>
  17 + <!-- 1. 工单编号(从URL获取展示) -->
  18 + <up-form-item
  19 + label="工单编号"
  20 + border-bottom
  21 + >
  22 + <up-input
  23 + v-model="workOrderForm.orderNo"
  24 + border="none"
  25 + readonly
  26 + placeholder="暂无工单编号"
  27 + ></up-input>
  28 + </up-form-item>
42 29  
43   - <!-- 3. 处理意见(非必填,文本域) -->
44   - <up-form-item
45   - label="处理意见"
46   - prop="reason"
47   - >
48   - <up-textarea
49   - placeholder="请输入处理意见(可选,最多200字)"
50   - v-model.trim="workOrderForm.reason"
51   - count
52   - maxlength="200"
53   - rows="4"
54   - ></up-textarea>
55   - </up-form-item>
  30 + <!-- 2. 养护员选择(必选,下拉框) -->
  31 + <up-form-item
  32 + label="养护员"
  33 + prop="assigneeName"
  34 + required
  35 + @click="handleActionSheetOpen('assignee'); hideKeyboard()"
  36 + >
  37 + <up-input
  38 + v-model="workOrderForm.assigneeName"
  39 + disabled
  40 + disabled-color="#ffffff"
  41 + placeholder="请选择养护员"
  42 + border="none"
  43 + ></up-input>
  44 + <template #right>
  45 + <up-icon name="arrow-right" size="16" color="#9CA3AF"></up-icon>
  46 + </template>
  47 + </up-form-item>
  48 + </view>
  49 +
  50 + <!-- ========== 分配说明(设计稿 .card) ========== -->
  51 + <view class="form-card">
  52 + <view class="sec-head">
  53 + <view class="sec-bar"></view>
  54 + <view class="sec-title">分配说明</view>
  55 + </view>
  56 +
  57 + <!-- 3. 分配说明(非必填,文本域) -->
  58 + <up-form-item
  59 + prop="reason"
  60 + >
  61 + <up-textarea
  62 + placeholder="请输入分配说明"
  63 + v-model.trim="workOrderForm.reason"
  64 + count
  65 + maxlength="200"
  66 + rows="4"
  67 + ></up-textarea>
  68 + </up-form-item>
  69 + </view>
56 70 </up-form>
57 71 </view>
58 72  
... ... @@ -60,7 +74,7 @@
60 74 <view class="fixed-bottom-btn-wrap">
61 75 <up-button
62 76 type="primary"
63   - text="提交"
  77 + text="确认分配"
64 78 @click="submitWorkOrder"
65 79 ></up-button>
66 80 </view>
... ... @@ -279,15 +293,106 @@ const submitWorkOrder = async () =&gt; {
279 293 </script>
280 294  
281 295 <style lang="scss" scoped>
282   -// 全局页面样式
  296 +// 页面容器:浅灰底 + 给底部固定栏(按钮 88rpx + 上下各 24rpx)留空间
283 297 .page-container {
284   -
  298 + min-height: 100vh;
  299 + padding-bottom: calc(180rpx + constant(safe-area-inset-bottom));
  300 + padding-bottom: calc(180rpx + env(safe-area-inset-bottom));
  301 + background-color: #F4F6FA;
285 302 }
286 303  
287   -// 表单内容容器
  304 +// 表单内容容器:透明底,左右 24rpx(覆盖全局 commonPageLRpadding 的 15px)
288 305 .work-order-form-content {
289   - background: #fff;
290   - margin-top: 10rpx;
  306 + padding: 0 24rpx;
  307 + background: transparent;
  308 +}
  309 +
  310 +// 白色卡片:8px 圆角 + 卡片阴影(设计稿 .card)
  311 +.form-card {
  312 + margin-top: 24rpx;
  313 + padding: 8rpx 24rpx;
  314 + background-color: #ffffff;
  315 + border-radius: 16rpx;
  316 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  317 +}
  318 +
  319 +// 区块标题:蓝色竖条 + 标题文字
  320 +.sec-head {
  321 + display: flex;
  322 + align-items: center;
  323 + gap: 12rpx;
  324 + padding: 20rpx 0 8rpx;
  325 +}
  326 +
  327 +.sec-bar {
  328 + width: 6rpx;
  329 + height: 28rpx;
  330 + background-color: #2563EB;
  331 + border-radius: 3rpx;
  332 +}
  333 +
  334 +.sec-title {
  335 + font-size: 30rpx;
  336 + font-weight: 500;
  337 + color: #1F2937;
  338 +}
  339 +
  340 +// 表单行:上下 24rpx(左右由卡片内边距控制)
  341 +:deep(.u-form-item__body) {
  342 + padding: 24rpx 0 !important;
  343 +}
  344 +
  345 +// 工单信息卡片:输入值右对齐
  346 +.form-card--info :deep(.u-input__content__field-wrapper__field) {
  347 + text-align: right;
  348 + font-size: 28rpx;
  349 + color: #1F2937;
  350 +}
  351 +
  352 +// 分配说明:文本域浅灰底 + 圆角、去掉默认描边(设计稿 .textarea)
  353 +.form-card :deep(.u-textarea) {
  354 + border: none;
  355 + background-color: #F4F6FA;
  356 + border-radius: 8rpx;
  357 +}
  358 +
  359 +.form-card :deep(.u-textarea__field) {
  360 + font-size: 28rpx;
  361 + color: #1F2937;
  362 +}
  363 +
  364 +// 字数统计贴灰底显示(组件内部写死了白底,需 !important 覆盖)
  365 +.form-card :deep(.u-textarea__count) {
  366 + background-color: transparent !important;
  367 + color: #9CA3AF;
  368 +}
  369 +
  370 +// 底部固定操作栏:白底 + 上分隔线 + 蓝色渐变主按钮(设计稿 .bar / .btn.pri)
  371 +.fixed-bottom-btn-wrap {
  372 + position: fixed;
  373 + left: 0;
  374 + right: 0;
  375 + bottom: 0;
  376 + z-index: 10;
  377 + padding: 24rpx 24rpx calc(24rpx + constant(safe-area-inset-bottom));
  378 + padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
  379 + background-color: #ffffff;
  380 + border-top: 1rpx solid #E8EBF0;
  381 + box-shadow: 0 -8rpx 28rpx rgba(17, 24, 39, 0.06);
  382 +
  383 + :deep(.u-button) {
  384 + height: 88rpx !important;
  385 + border-radius: 16rpx !important;
  386 + border: none !important;
  387 + /* 与顶部导航栏同色 */
  388 + background-color: #2563EB !important;
  389 + background-image: none !important;
  390 + }
  391 +
  392 + :deep(.u-button__text) {
  393 + font-size: 30rpx !important;
  394 + font-weight: 500 !important;
  395 + }
291 396 }
292 397  
293 398  
... ...
pages-sub/problem/work-order-manage/index.vue
... ... @@ -7,8 +7,8 @@
7 7 <up-tabs
8 8 v-model="activeTab"
9 9 :list="tabList"
10   - active-color="#1989fa"
11   - inactive-color="#666"
  10 + active-color="#2563EB"
  11 + inactive-color="#606266"
12 12 font-size="30rpx"
13 13 @click="handleTabChange"
14 14 />
... ... @@ -57,7 +57,7 @@
57 57 <empty-view/>
58 58 </template>
59 59  
60   - <view class="common-card-list" style="padding-top: 200rpx;padding-bottom: 30rpx">
  60 + <view class="common-card-list" style="padding-top: 216rpx;padding-bottom: 180rpx">
61 61 <!-- 待办工单卡片 -->
62 62 <up-card
63 63 v-if="activeTab == 0"
... ... @@ -70,6 +70,8 @@
70 70 >
71 71 <template #body>
72 72 <view class="card-body">
  73 + <!-- 卡片标题:工单名称(设计稿 .card-title) -->
  74 + <view class="card-title u-line-1">{{ item.orderName || '未填写' }}</view>
73 75 <view class="u-body-item u-flex">
74 76 <view class="u-body-item-title">工单编号:</view>
75 77 <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view>
... ... @@ -79,10 +81,6 @@
79 81 <view class="u-line-1 u-body-value">{{ item.lonLatAddress || '-' }}</view>
80 82 </view>
81 83 <view class="u-body-item u-flex">
82   - <view class="u-body-item-title">工单名称:</view>
83   - <view class="u-line-1 u-body-value">{{ item.orderName || '未填写' }}</view>
84   - </view>
85   - <view class="u-body-item u-flex">
86 84 <view class="u-body-item-title">情况描述:</view>
87 85 <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view>
88 86 </view>
... ... @@ -101,16 +99,17 @@
101 99 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
102 100 </view>
103 101 <!-- 操作按钮行 -->
104   - <view class="u-body-item task-btn-row mt-20">
  102 + <view class="u-body-item task-btn-row mt-20"
  103 + :style="{'--cols': getActionRowCols(actionBtnCount(item))}">
105 104 <!-- 已配置工作流动作:按配置逐个渲染按钮,点击直接执行对应动作,不再弹「请选择操作」 -->
106 105 <template v-if="hasConfiguredActions(item)">
107 106 <view
108 107 v-for="action in item.configuredActions"
109 108 :key="action.code"
110   - :class="['task-btn', 'task-btn--' + getActionButtonType(action.code)]"
  109 + :class="['task-btn', 'task-btn--' + getActionButtonType(action.code, action.name)]"
111 110 @click.stop="handleUnifiedProcess(item, action)"
112 111 >{{ action.name }}</view>
113   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  112 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
114 113 </template>
115 114 <!-- 未配置:沿用原有节点按钮 -->
116 115 <template v-else>
... ... @@ -120,7 +119,7 @@
120 119 @click.stop="handleRenew(item)">重新提交</view>
121 120 <view class="task-btn task-btn--primary"
122 121 @click.stop="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</view>
123   - <view class="task-btn task-btn--info" @click.stop="handleDetail(item)">详情</view>
  122 + <view class="task-btn task-btn--primary" @click.stop="handleDetail(item)">详情</view>
124 123 </template>
125 124 </view>
126 125 </view>
... ... @@ -139,13 +138,8 @@
139 138 >
140 139 <template #body>
141 140 <view class="card-body">
142   -
143   -<!-- <view class=" ">-->
144   -<!-- <up-button type="primary" size="mini" @click="handleDetail(item)">工单详情</up-button>-->
145   -<!-- </view>-->
146   - <view class="common-custom-btn " style="--btn-top: 130px;" @click="handleDetail(item)">
147   - 工单详情
148   - </view>
  141 + <!-- 卡片标题:工单名称(设计稿 .card-title) -->
  142 + <view class="card-title u-line-1">{{ item.orderName || '未填写' }}</view>
149 143  
150 144 <view class="u-body-item u-flex">
151 145 <view class="u-body-item-title">工单编号:</view>
... ... @@ -156,20 +150,13 @@
156 150 <view class="u-line-1 u-body-value">{{ item.lonLatAddress || '-' }}</view>
157 151 </view>
158 152 <view class="u-body-item u-flex">
159   - <view class="u-body-item-title">工单名称:</view>
160   - <view class="u-line-1 u-body-value">{{ item.orderName || '未填写' }}</view>
161   - </view>
162   - <view class="u-body-item u-flex">
163 153 <view class="u-body-item-title">情况描述:</view>
164 154 <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view>
165 155 </view>
166 156  
167 157 <view class="u-body-item u-flex common-justify-between common-item-center">
168   - <view class="u-body-item-title">紧急程度:{{ uni.$dict.getDictLabel('workorder_pressing_type', item.pressingType) }}
169   - </view>
170   -<!-- <view class=" ">-->
171   -<!-- <up-button type="primary" size="mini" @click="handleDetail(item)">工单详情</up-button>-->
172   -<!-- </view>-->
  158 + <view class="u-body-item-title">紧急程度:</view>
  159 + <view class="u-line-1 u-body-value">{{ uni.$dict.getDictLabel('workorder_pressing_type', item.pressingType) }}</view>
173 160 </view>
174 161 <view class="u-body-item u-flex">
175 162 <view class="u-body-item-title">工单状态:</view>
... ... @@ -179,6 +166,11 @@
179 166 <view class="u-body-item-title">提交时间:</view>
180 167 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
181 168 </view>
  169 +
  170 + <!-- 底部操作:分隔线 + 查看详情(设计稿 .card-foot) -->
  171 + <view class="card-foot">
  172 + <view class="foot-btn" @click="handleDetail(item)">工单详情</view>
  173 + </view>
182 174 </view>
183 175 </template>
184 176 </up-card>
... ... @@ -298,7 +290,7 @@ import {
298 290 } from '@/api/work-order-manage/work-order-manage'
299 291 // 从用户store获取角色信息
300 292 import { useUserStore } from '@/pinia/user';
301   -import { nextStepMap, buzStatusMap, getActionButtonType, toWorkerImplementPage } from '@/common/utils/common'
  293 +import { nextStepMap, buzStatusMap, getActionButtonType, getActionRowCols, toWorkerImplementPage } from '@/common/utils/common'
302 294 // 引入图片上传组合式函数(与参考页面一致)
303 295 import { useUploadImgs } from '@/common/utils/useUploadImgs'
304 296  
... ... @@ -346,7 +338,6 @@ const rejectImgs = useUploadImgs({
346 338 fieldName: 'rejectImgs' // 自定义字段名
347 339 })
348 340  
349   -
350 341 // ========== 验收弹窗相关状态(含图片上传) ==========
351 342 const acceptModalShow = ref(false); // 验收弹窗显示开关
352 343 const acceptRadioValue = ref('0'); // 单选框值,默认0(通过)
... ... @@ -389,7 +380,6 @@ const openMapNav = (item) =&gt; {
389 380 // });
390 381 };
391 382  
392   -
393 383 // 分页查询列表
394 384 const queryList = async (pageNo, pageSize) => {
395 385 try {
... ... @@ -550,6 +540,17 @@ const getProcessButtonText = (item) =&gt; {
550 540 const hasConfiguredActions = (item) =>
551 541 Array.isArray(item?.configuredActions) && item.configuredActions.length > 0
552 542  
  543 +/** 操作按钮行按钮数量:单个占一半宽度,多个等分,最多 5 个一行 */
  544 +const actionBtnCount = (item) => {
  545 + if (hasConfiguredActions(item)) {
  546 + return item.configuredActions.length + 1 // 配置动作 + 详情
  547 + }
  548 + let count = 2 // 主按钮 + 详情
  549 + if (showRejectButton(item)) count++
  550 + if (nextStepMap[item.taskKey]?.renewShow) count++
  551 + return count
  552 +}
  553 +
553 554 /** 待办-处理工单:已配置统一动作时直接执行点击的配置动作,否则回退原有处理 */
554 555 const handleUnifiedProcess = async (item, action = null) => {
555 556 const actions = Array.isArray(item?.configuredActions)
... ... @@ -818,7 +819,7 @@ onUnload(() =&gt; {
818 819 <style scoped lang="scss">
819 820 .page-container {
820 821 min-height: 100vh;
821   - background-color: #fafafa;
  822 + background-color: #F4F6FA;
822 823 }
823 824  
824 825 // 顶部固定区域
... ... @@ -852,39 +853,107 @@ onUnload(() =&gt; {
852 853 }
853 854 }
854 855  
855   -// 工单卡片样式
  856 +// 工单卡片样式:白底 / 16rpx 圆角 / 卡片阴影(设计稿 .card)
856 857 .order-card {
857   - margin: 0 20rpx 20rpx;
  858 + margin: 0 24rpx 24rpx;
858 859 background: #fff;
859   - border-radius: 12rpx;
860   - box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
  860 + border-radius: 16rpx;
  861 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  862 + overflow: hidden;
  863 +
  864 + // 卡片内边距 24rpx(覆盖 u-card 默认的 15px)
  865 + :deep(.u-card__body) {
  866 + padding: 24rpx !important;
  867 + }
  868 +}
  869 +
  870 +// 卡片标题:工单名称(设计稿 .card-title)
  871 +.card-title {
  872 + font-size: 32rpx;
  873 + font-weight: 500;
  874 + color: #1F2937;
  875 + line-height: 1.4;
  876 + margin-bottom: 16rpx;
  877 +}
  878 +
  879 +// 信息行间距(覆盖全局 6rpx,设计稿行距更舒展)
  880 +.card-body .u-body-item {
  881 + margin-bottom: 12rpx !important;
  882 +
  883 + &:last-child {
  884 + margin-bottom: 0 !important;
  885 + }
861 886 }
862   -// 卡片操作按钮:自动换行、右对齐,动作多时每行 3~4 个,不再整行铺满
  887 +
  888 +// 卡片操作按钮:单个占页面一半宽度(左对齐),多个等分,每行最多 5 个,超出自动换行
863 889 .task-btn-row {
  890 + display: grid;
  891 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  892 + column-gap: 16rpx;
  893 + row-gap: 16rpx;
  894 + margin-bottom: 0;
  895 + padding-top: 24rpx;
  896 + border-top: 1rpx solid #E8EBF0;
  897 +}
  898 +
  899 +// 底部操作行:分隔线 + 右对齐次要按钮(设计稿 .card-foot)
  900 +.card-foot {
864 901 display: flex;
865   - flex-wrap: wrap;
866 902 justify-content: flex-end;
867   - margin-bottom: -10rpx;
  903 + margin-top: 24rpx;
  904 + padding-top: 24rpx;
  905 + border-top: 1rpx solid #E8EBF0;
  906 +}
  907 +
  908 +.foot-btn {
  909 + box-sizing: border-box;
  910 + display: flex;
  911 + align-items: center;
  912 + justify-content: center;
  913 + min-width: 140rpx;
  914 + height: 56rpx;
  915 + padding: 0 24rpx;
  916 + font-size: 24rpx;
  917 + color: #ffffff;
  918 + background-color: #3B9DFF; // 与「详情」按钮统一蓝色
  919 + border: 1rpx solid #3B9DFF;
  920 + border-radius: 8rpx;
  921 +}
  922 +
  923 +.foot-btn:active {
  924 + background-color: #2E8AE6;
  925 + border-color: #2E8AE6;
868 926 }
869 927  
870 928 .task-btn {
871 929 box-sizing: border-box;
872 930 height: 56rpx;
873 931 line-height: 56rpx;
874   - padding: 0 24rpx;
875   - margin: 0 0 10rpx 12rpx;
  932 + padding: 0 12rpx;
876 933 border-radius: 8rpx;
877 934 font-size: 24rpx;
878 935 color: #fff;
  936 + text-align: center;
879 937 white-space: nowrap;
  938 + overflow: hidden;
  939 + text-overflow: ellipsis;
880 940 }
881 941  
  942 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
882 943 .task-btn--primary {
883   - background-color: #3c9cff;
  944 + background-color: #3B9DFF;
  945 +}
  946 +
  947 +.task-btn--assign {
  948 + background-color: #2563EB;
  949 +}
  950 +
  951 +.task-btn--transfer {
  952 + background-color: #0891B2;
884 953 }
885 954  
886 955 .task-btn--success {
887   - background-color: #5ac725;
  956 + background-color: #078d0a;
888 957 }
889 958  
890 959 .task-btn--warning {
... ... @@ -899,8 +968,6 @@ onUnload(() =&gt; {
899 968 background-color: #909399;
900 969 }
901 970  
902   -
903   -
904 971 // 回退modal样式
905 972 .reject-modal-content {
906 973 width: 100%;
... ... @@ -910,7 +977,7 @@ onUnload(() =&gt; {
910 977  
911 978 .textarea-label {
912 979 font-size: 28rpx;
913   - color: #333;
  980 + color: #1a1a1a;
914 981 margin-bottom: 10rpx;
915 982  
916 983 .required-mark {
... ... @@ -924,7 +991,7 @@ onUnload(() =&gt; {
924 991  
925 992 .upload-title {
926 993 font-size: 28rpx;
927   - color: #333;
  994 + color: #1a1a1a;
928 995 margin-bottom: 10rpx;
929 996 }
930 997 }
... ...
pages-sub/problem/work-order-manage/order-detail.vue
... ... @@ -5,7 +5,7 @@
5 5 v-if="loading"
6 6 :loading="true"
7 7 title="加载中..."
8   - color="#3c9cff"
  8 + color="#2563EB"
9 9 ></up-loading-page>
10 10  
11 11 <!-- 主内容容器 -->
... ... @@ -17,8 +17,8 @@
17 17 :list="topTabList"
18 18 :scrollable="false"
19 19 sticky
20   - active-color="#3c9cff"
21   - inactive-color="#666"
  20 + active-color="#2563EB"
  21 + inactive-color="#606266"
22 22 class="top-tabs"
23 23 @click="activeTopTabClick"
24 24 ></up-tabs>
... ... @@ -29,6 +29,11 @@
29 29 <!-- 1. 工单详情Tab -->
30 30 <view v-show="activeTopTab == 0" class="detail-content">
31 31 <up-cell-group :border="false" class="detail-cell-group">
  32 + <!-- 区块标题:工单信息(设计稿 .card-title) -->
  33 + <view class="sec-head">
  34 + <view class="sec-bar"></view>
  35 + <view class="sec-title">工单信息</view>
  36 + </view>
32 37 <!-- 工单编号 -->
33 38 <up-cell title="工单编号" :value="orderDetail.orderNo || '--'" align="middle"></up-cell>
34 39  
... ... @@ -63,16 +68,6 @@
63 68 </template>
64 69 </up-cell>
65 70  
66   - <!-- 情况描述 -->
67   - <up-cell>
68   - <template #title>
69   - <view style="min-width: 200rpx">情况描述</view>
70   - </template>
71   - <template #value>
72   - <view class="common-text-color up-line-1">{{ orderDetail.remark || '--' }}</view>
73   - </template>
74   - </up-cell>
75   -
76 71 <!-- 紧急程度 -->
77 72 <up-cell
78 73 title="紧急程度"
... ... @@ -100,24 +95,6 @@
100 95 </template>
101 96 </up-cell>
102 97  
103   - <!-- 问题照片 -->
104   - <up-cell title="问题照片">
105   - <template #value>
106   - <view class="cell-content-wrap">
107   - <up-album
108   - v-if="!!orderDetail.problemsImgs?.length"
109   - :urls="orderDetail.problemsImgs.slice(0, 3)"
110   - :singleSize="70"
111   - :multipleSize="70"
112   - :preview-full-image="true"
113   - ></up-album>
114   - <text v-else class="empty-text">暂无问题照片</text>
115   - </view>
116   - </template>
117   - </up-cell>
118   -
119   -
120   -
121 98 <up-cell title="重点巡检区域" :value="orderDetail.keyInspection==0?'否':'是'" align="middle"></up-cell>
122 99  
123 100 <!-- 希望完成时间 -->
... ... @@ -138,6 +115,41 @@
138 115 ></up-cell>
139 116 </up-cell-group>
140 117  
  118 + <!-- 情况描述(设计稿独立卡片) -->
  119 + <up-cell-group :border="false" class="detail-cell-group">
  120 + <view class="sec-head">
  121 + <view class="sec-bar"></view>
  122 + <view class="sec-title">情况描述</view>
  123 + </view>
  124 + <up-cell :border="false">
  125 + <template #value>
  126 + <view class="desc-text">{{ orderDetail.remark || '--' }}</view>
  127 + </template>
  128 + </up-cell>
  129 + </up-cell-group>
  130 +
  131 + <!-- 问题照片(设计稿独立卡片) -->
  132 + <up-cell-group :border="false" class="detail-cell-group">
  133 + <view class="sec-head">
  134 + <view class="sec-bar"></view>
  135 + <view class="sec-title">问题照片</view>
  136 + </view>
  137 + <up-cell :border="false">
  138 + <template #value>
  139 + <view class="cell-content-wrap">
  140 + <up-album
  141 + v-if="!!orderDetail.problemsImgs?.length"
  142 + :urls="orderDetail.problemsImgs.slice(0, 3)"
  143 + :singleSize="70"
  144 + :multipleSize="70"
  145 + :preview-full-image="true"
  146 + ></up-album>
  147 + <text v-else class="empty-text">暂无问题照片</text>
  148 + </view>
  149 + </template>
  150 + </up-cell>
  151 + </up-cell-group>
  152 +
141 153 <!-- 图片分类Tabs区块 -->
142 154 <view class="img-tabs-block" v-if="orderDetail.startImgs.length>0">
143 155 <up-cell-group :border="false">
... ... @@ -159,8 +171,8 @@
159 171 v-model="activeImgTab"
160 172 :list="imgTabList"
161 173 :scrollable="false"
162   - active-color="#3c9cff"
163   - inactive-color="#666"
  174 + active-color="#2563EB"
  175 + inactive-color="#606266"
164 176 class="img-tabs"
165 177 ></up-tabs>
166 178  
... ... @@ -180,7 +192,10 @@
180 192  
181 193 <!-- 作业填报明细(工单实施时按「业务类型+作业类型」动态字段配置填报) -->
182 194 <view class="work-field-block" v-if="workFieldValues.length > 0">
183   - <view class="work-field-title">作业填报</view>
  195 + <view class="sec-head">
  196 + <view class="sec-bar"></view>
  197 + <view class="sec-title">作业填报</view>
  198 + </view>
184 199 <up-cell-group :border="false">
185 200 <up-cell
186 201 v-for="item in workFieldValues"
... ... @@ -223,8 +238,8 @@
223 238 :list="processData.activityNodes"
224 239 :current="getCurrentStepIndex()"
225 240 direction="column"
226   - active-color="#3c9cff"
227   - inactive-color="#999"
  241 + active-color="#2563EB"
  242 + inactive-color="#909399"
228 243 class="vertical-steps"
229 244 >
230 245 <template>
... ... @@ -237,7 +252,7 @@
237 252 <view class="step-content-wrap">
238 253 <!-- 1. 原标题内容:节点名称 + 操作人 -->
239 254 <view class="step-title">
240   - {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }}
  255 + {{ item.name }}
241 256 </view>
242 257  
243 258 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) -->
... ... @@ -294,17 +309,18 @@
294 309 <!-- activeTab==0的时候才出现, 也就是待办 -->
295 310 <view v-if="activeTab==0&&(configuredActions||nextStepMap[orderDetail.taskKey])"
296 311 class="fixed-bottom-btn-wrap order-action-bar">
297   - <!-- 已配置工作流动作:每行最多 3 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
298   - <view v-if="hasConfiguredActions" class="order-action-row">
  312 + <!-- 已配置工作流动作:每行最多 5 个、超出自动换行,点击直接执行对应动作,不再弹「请选择操作」 -->
  313 + <view v-if="hasConfiguredActions" class="order-action-row"
  314 + :style="{'--cols': getActionRowCols(configuredActions.length)}">
299 315 <view
300 316 v-for="action in configuredActions"
301 317 :key="action.code"
302   - :class="['order-action-btn', 'order-action-btn--' + getActionButtonType(action.code)]"
  318 + :class="['order-action-btn', 'order-action-btn--' + getActionButtonType(action.code, action.name)]"
303 319 @click.stop="handleUnifiedProcess(orderDetail, action)"
304 320 >{{ action.name }}</view>
305 321 </view>
306   - <!-- 未配置:沿用原有节点按钮(整行展示) -->
307   - <view v-else class="order-action-row order-action-row--single">
  322 + <!-- 未配置:沿用原有节点按钮 -->
  323 + <view v-else class="order-action-row" :style="{'--cols': getActionRowCols(legacyActionCount)}">
308 324 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning"
309 325 @click.stop="handleUnifiedReject(orderDetail)">回退</view>
310 326 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success"
... ... @@ -418,7 +434,7 @@ import {
418 434 getTaskActions
419 435 } from '@/api/work-order-manage/work-order-manage';
420 436 import {getWorkRecordValues} from '@/api/common'
421   -import {nextStepMap, buzStatusMap, calculateFormatTimeDiff, getActionButtonType, toWorkerImplementPage} from '@/common/utils/common'
  437 +import {nextStepMap, buzStatusMap, calculateFormatTimeDiff, getActionButtonType, getActionRowCols, toWorkerImplementPage} from '@/common/utils/common'
422 438 // 引入图片上传组合式函数
423 439 import {useUploadImgs} from '@/common/utils/useUploadImgs'
424 440  
... ... @@ -813,15 +829,20 @@ const showRejectButton = computed(() =&gt; {
813 829 const hasConfiguredActions = computed(() =>
814 830 Array.isArray(configuredActions.value) && configuredActions.value.length > 0)
815 831  
816   -/** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容 */
  832 +/** 未配置统一动作时的按钮数量:主按钮 + 可选的回退/重新提交 */
  833 +const legacyActionCount = computed(() => {
  834 + let count = 1
  835 + if (showRejectButton.value) count++
  836 + if (nextStepMap[orderDetail.value.taskKey]?.renewShow) count++
  837 + return count
  838 +})
  839 +
  840 +/** 底部操作栏行数:详情内容据此预留底部间距,避免按钮遮挡内容(每行最多 5 个) */
817 841 const actionBarRows = computed(() => {
818 842 if (hasConfiguredActions.value) {
819   - return Math.ceil(configuredActions.value.length / 3)
  843 + return Math.ceil(configuredActions.value.length / 5)
820 844 }
821   - let rows = 1
822   - if (showRejectButton.value) rows++
823   - if (nextStepMap[orderDetail.value.taskKey]?.renewShow) rows++
824   - return rows
  845 + return 1
825 846 })
826 847  
827 848 /** 主按钮文案:已配置统一动作时取配置的动作名称,未配置时沿用原有节点规则 */
... ... @@ -1065,6 +1086,7 @@ onShow(() =&gt; {
1065 1086 // 全局样式
1066 1087 .page-container {
1067 1088 min-height: 100vh;
  1089 + background-color: #F4F6FA;
1068 1090 }
1069 1091  
1070 1092 // 主内容容器
... ... @@ -1072,6 +1094,27 @@ onShow(() =&gt; {
1072 1094 padding-bottom: 80rpx;
1073 1095 }
1074 1096  
  1097 +// 区块标题:蓝色竖条 + 标题(设计稿 .card-title)
  1098 +.sec-head {
  1099 + display: flex;
  1100 + align-items: center;
  1101 + gap: 12rpx;
  1102 + padding: 20rpx 24rpx 8rpx;
  1103 +}
  1104 +
  1105 +.sec-bar {
  1106 + width: 6rpx;
  1107 + height: 28rpx;
  1108 + background-color: #2563EB;
  1109 + border-radius: 3rpx;
  1110 +}
  1111 +
  1112 +.sec-title {
  1113 + font-size: 30rpx;
  1114 + font-weight: 500;
  1115 + color: #1F2937;
  1116 +}
  1117 +
1075 1118 // 顶部Tabs
1076 1119 .top-tabs {
1077 1120 //background-color: #fff;
... ... @@ -1084,45 +1127,68 @@ onShow(() =&gt; {
1084 1127  
1085 1128 // 工单详情内容
1086 1129 .detail-content {
  1130 + // 白色卡片:16rpx 圆角 + 卡片阴影(设计稿 .card)
1087 1131 .detail-cell-group {
1088 1132 background-color: #fff;
1089   - margin-bottom: 20rpx;
  1133 + margin: 0 24rpx 24rpx !important;
  1134 + border-radius: 16rpx;
  1135 + overflow: hidden;
  1136 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  1137 +
  1138 + // 行内边距 24rpx(覆盖 u-cell 默认的 10px 上下)
  1139 + :deep(.u-cell__body) {
  1140 + padding: 20rpx 24rpx !important;
  1141 + }
1090 1142 }
1091 1143  
1092 1144 .cell-content-wrap {
1093 1145 // 保持原有样式,兼容up-album布局
1094 1146 }
1095 1147  
  1148 + // 情况描述:整段左对齐展示(设计稿 .desc)
  1149 + .desc-text {
  1150 + width: 100%;
  1151 + text-align: left;
  1152 + font-size: 28rpx;
  1153 + color: #4B5563;
  1154 + line-height: 1.6;
  1155 + word-break: break-all;
  1156 + }
  1157 +
1096 1158 .empty-text {
1097   - color: #999;
1098   - font-size: 26rpx;
  1159 + color: #9CA3AF;
  1160 + font-size: 28rpx;
1099 1161 }
1100 1162 }
1101 1163  
1102   -// 图片分类Tabs区块
  1164 +// 图片分类Tabs区块:整块作为一张卡片
1103 1165 .img-tabs-block {
  1166 + margin: 0 24rpx 24rpx;
1104 1167 background-color: #fff;
1105   - //border-radius: 12rpx;
1106   - //padding: 16rpx;
  1168 + border-radius: 16rpx;
  1169 + overflow: hidden;
  1170 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  1171 +
  1172 + // 内部 cell-group 不再单独成卡,避免卡片套卡片
  1173 + :deep(.u-cell-group) {
  1174 + margin: 0 !important;
  1175 + border-radius: 0 !important;
  1176 + box-shadow: none !important;
  1177 + }
  1178 +
  1179 + .img-tabs {
  1180 + padding: 0 24rpx;
  1181 + }
1107 1182  
1108 1183 // 图片内容区
1109 1184 .img-tab-content {
1110   - padding: 20rpx 15px ;
1111   - text-align: center;
1112   - //min-height: 120rpx;
1113   - //display: flex;
1114   - //align-items: center;
1115   - //justify-content: center;
1116   - //
1117   - .img-album {
1118   - //width: 100%;
1119   -
1120   - }
  1185 + padding: 16rpx 24rpx 24rpx;
  1186 + text-align: left;
1121 1187  
1122 1188 .empty-img-text {
1123 1189 height: 75px;
1124 1190 line-height: 75px;
1125   - color: #999;
  1191 + color: #9CA3AF;
1126 1192 font-size: 28rpx;
1127 1193 }
1128 1194 }
... ... @@ -1137,12 +1203,14 @@ onShow(() =&gt; {
1137 1203 margin-top: 100rpx;
1138 1204 }
1139 1205  
1140   - // 竖向步骤条容器样式
  1206 + // 竖向步骤条容器样式:白色卡片(设计稿 .card)
1141 1207 .vertical-steps {
1142 1208 //width: 100%;
  1209 + margin: 24rpx 24rpx 0;
1143 1210 background-color: #fff;
1144   - padding: 20rpx;
1145   - border-radius: 12rpx;
  1211 + padding: 24rpx;
  1212 + border-radius: 16rpx;
  1213 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
1146 1214 display: flex;
1147 1215 flex-direction: column;
1148 1216 gap: 20rpx; // 步骤项间距
... ... @@ -1158,13 +1226,13 @@ onShow(() =&gt; {
1158 1226 .step-title {
1159 1227 font-size: 30rpx;
1160 1228 font-weight: 600;
1161   - color: #333;
  1229 + color: #1a1a1a;
1162 1230 margin-bottom: 12rpx;
1163 1231  
1164 1232 .operator-name {
1165 1233 font-size: 30rpx;
1166 1234 font-weight: 600;
1167   - color: #333;
  1235 + color: #1a1a1a;
1168 1236 margin-left: 20rpx;
1169 1237 }
1170 1238 }
... ... @@ -1172,7 +1240,7 @@ onShow(() =&gt; {
1172 1240 // 描述(时间 + 处理说明)样式
1173 1241 .step-desc {
1174 1242 font-size: 24rpx;
1175   - color: #666;
  1243 + color: #606266;
1176 1244 line-height: 1.6;
1177 1245 margin-bottom: 12rpx;
1178 1246  
... ... @@ -1199,7 +1267,7 @@ onShow(() =&gt; {
1199 1267  
1200 1268 .no-img-tip {
1201 1269 font-size: 24rpx;
1202   - color: #999;
  1270 + color: #909399;
1203 1271 margin-top: 10rpx;
1204 1272 }
1205 1273 }
... ... @@ -1212,7 +1280,7 @@ onShow(() =&gt; {
1212 1280  
1213 1281 .upload-title {
1214 1282 font-size: 28rpx;
1215   - color: #333;
  1283 + color: #1a1a1a;
1216 1284 margin-bottom: 10rpx;
1217 1285 }
1218 1286 }
... ... @@ -1261,7 +1329,7 @@ onShow(() =&gt; {
1261 1329 }
1262 1330  
1263 1331 // 底部动作按钮:动作多时自动换行
1264   -// 底部操作栏:白底 + 顶部投影,按钮每行最多 3 个,避免多动作时整屏遮挡工单详情
  1332 +// 底部操作栏:白底 + 顶部投影,按钮每行最多 5 个,避免多动作时整屏遮挡工单详情
1265 1333 .order-action-bar {
1266 1334 background-color: #fff;
1267 1335 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
... ... @@ -1271,20 +1339,19 @@ onShow(() =&gt; {
1271 1339 }
1272 1340  
1273 1341 .order-action-row {
1274   - display: flex;
1275   - flex-wrap: wrap;
1276   - margin: -6rpx;
  1342 + display: grid;
  1343 + grid-template-columns: repeat(var(--cols, 5), minmax(0, 1fr));
  1344 + column-gap: 12rpx;
  1345 + row-gap: 12rpx;
1277 1346 }
1278 1347  
1279 1348 .order-action-btn {
1280 1349 box-sizing: border-box;
1281   - width: calc((100% - 36rpx) / 3);
1282 1350 height: 68rpx;
1283 1351 line-height: 68rpx;
1284   - margin: 6rpx;
1285 1352 padding: 0 8rpx;
1286 1353 border-radius: 8rpx;
1287   - font-size: 26rpx;
  1354 + font-size: 28rpx;
1288 1355 text-align: center;
1289 1356 color: #fff;
1290 1357 white-space: nowrap;
... ... @@ -1292,17 +1359,21 @@ onShow(() =&gt; {
1292 1359 text-overflow: ellipsis;
1293 1360 }
1294 1361  
1295   -// 未配置统一动作时按钮整行展示,保持原有观感
1296   -.order-action-row--single .order-action-btn {
1297   - width: 100%;
  1362 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
  1363 +.order-action-btn--primary {
  1364 + background-color: #3B9DFF;
1298 1365 }
1299 1366  
1300   -.order-action-btn--primary {
1301   - background-color: #3c9cff;
  1367 +.order-action-btn--assign {
  1368 + background-color: #2563EB;
  1369 +}
  1370 +
  1371 +.order-action-btn--transfer {
  1372 + background-color: #0891B2;
1302 1373 }
1303 1374  
1304 1375 .order-action-btn--success {
1305   - background-color: #5ac725;
  1376 + background-color: #078d0a;
1306 1377 }
1307 1378  
1308 1379 .order-action-btn--warning {
... ... @@ -1330,16 +1401,23 @@ onShow(() =&gt; {
1330 1401 padding-bottom: 390rpx;
1331 1402 }
1332 1403  
1333   -// 作业填报明细
  1404 +// 作业填报明细:白色卡片(设计稿 .card)
1334 1405 .work-field-block {
1335   - margin-top: 20rpx;
  1406 + margin: 0 24rpx 24rpx;
  1407 + background-color: #fff;
  1408 + border-radius: 16rpx;
  1409 + overflow: hidden;
  1410 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
1336 1411  
1337   - .work-field-title {
1338   - padding: 16rpx 30rpx;
1339   - font-size: 30rpx;
1340   - font-weight: 600;
1341   - color: #303133;
1342   - background: #fff;
  1412 + // 内部 cell-group 不再单独成卡
  1413 + :deep(.u-cell-group) {
  1414 + margin: 0 !important;
  1415 + border-radius: 0 !important;
  1416 + box-shadow: none !important;
  1417 + }
  1418 +
  1419 + :deep(.u-cell__body) {
  1420 + padding: 20rpx 24rpx !important;
1343 1421 }
1344 1422  
1345 1423 .work-field-value {
... ... @@ -1359,8 +1437,8 @@ onShow(() =&gt; {
1359 1437  
1360 1438 .work-field-file {
1361 1439 max-width: 420rpx;
1362   - font-size: 26rpx;
1363   - color: #3c9cff;
  1440 + font-size: 28rpx;
  1441 + color: #2563EB;
1364 1442 }
1365 1443 }
1366 1444 }
... ...
pages.json
... ... @@ -310,9 +310,9 @@
310 310 }
311 311 },
312 312 "globalStyle": {
313   - "navigationBarTextStyle": "black",
  313 + "navigationBarTextStyle": "white",
314 314 "navigationBarTitleText": "JCSS管理系统",
315   - "navigationBarBackgroundColor": "#ffffff",
  315 + "navigationBarBackgroundColor": "#2563EB",
316 316 "backgroundColor": "#f8f8f8"
317 317 }
318 318 }
319 319 \ No newline at end of file
... ...
pages/index/index.vue
... ... @@ -46,7 +46,7 @@
46 46 <up-grid :border="false" col="4">
47 47 <up-grid-item v-for="(baseListItem, baseListIndex) in baseList" :key="baseListIndex">
48 48 <view class="grid-item-icon-box">
49   - <up-icon :name="baseListItem.name" size="32" color="#1677ff"></up-icon>
  49 + <up-icon :name="baseListItem.name" size="32" color="#2563EB"></up-icon>
50 50 <text class="grid-num-icon">{{ baseListItem.num }}</text>
51 51 <text class="grid-label-icon">{{ baseListItem.title }}</text>
52 52 </view>
... ... @@ -87,7 +87,7 @@
87 87 <!-- 顶部进度提示栏 -->
88 88 <view v-if="showTipHeader" class="tip-header">
89 89 <up-icon name="checkmark-circle" color="#00b42a" size="20"></up-icon>
90   - <text style="color: #1677ff;">今日组内:您已经完成{{ finishNum }}项,小组均值{{ avgNum }}项</text>
  90 + <text style="color: #2563EB;">今日组内:您已经完成{{ finishNum }}项,小组均值{{ avgNum }}项</text>
91 91 </view>
92 92 <scroll-view class="task-list-container" scroll-y @scroll="onListScroll" @scrolltoupper="handleTouchTop" enhanced>
93 93 <view v-if="taskList.length === 0" class="empty-box">
... ... @@ -635,9 +635,9 @@ onUnload(() =&gt; {
635 635 </script>
636 636  
637 637 <style scoped lang="scss">
638   -$primary-color: #1677ff;
  638 +$primary-color: #2563EB;
639 639 $danger-color: #E53935;
640   -$text-color: #333;
  640 +$text-color: #1a1a1a;
641 641 $text-color-light: #666;
642 642 $text-placeholder: #999;
643 643 $bg-color: #f5f5f7;
... ... @@ -665,7 +665,7 @@ $border-color: #e5e5e5;
665 665 align-items: center;
666 666 color: #fff;
667 667 .username {
668   - font-size: 32rpx;
  668 + font-size: 30rpx;
669 669 margin-bottom: 4rpx;
670 670 }
671 671 .login-desc {
... ... @@ -764,11 +764,11 @@ $border-color: #e5e5e5;
764 764 .main-tab-item {
765 765 padding: 24rpx 16rpx;
766 766 font-size: 30rpx;
767   - color: #666;
  767 + color: #606266;
768 768 position: relative;
769 769 transition: color 0.24s;
770 770 &.active {
771   - color: #1677ff;
  771 + color: #2563EB;
772 772 font-weight: 500;
773 773 &::after {
774 774 content: '';
... ... @@ -777,7 +777,7 @@ $border-color: #e5e5e5;
777 777 bottom: 0;
778 778 width: 100%;
779 779 height: 4rpx;
780   - background-color: #1677ff;
  780 + background-color: #2563EB;
781 781 border-radius: 2rpx;
782 782 }
783 783 }
... ... @@ -794,7 +794,7 @@ $border-color: #e5e5e5;
794 794 .tab-capsule {
795 795 padding: 10rpx 20rpx;
796 796 font-size: 28rpx;
797   - color: #999;
  797 + color: #909399;
798 798 background: #f5f5f5;
799 799 border-radius: 0;
800 800 transition: all 0.2s ease;
... ... @@ -878,7 +878,7 @@ $border-color: #e5e5e5;
878 878 display: flex;
879 879 align-items: flex-start;
880 880 gap: 6rpx;
881   - font-size: 26rpx;
  881 + font-size: 28rpx;
882 882 color: $text-color-light;
883 883 margin-top: $spacing-sm;
884 884 align-items: center;
... ... @@ -900,12 +900,12 @@ $border-color: #e5e5e5;
900 900 .grid-num-icon {
901 901 font-size: 40rpx;
902 902 font-weight: 600;
903   - color: #333;
  903 + color: #1a1a1a;
904 904 margin-top: 8rpx;
905 905 }
906 906 .grid-label-icon {
907   - font-size: 22rpx;
908   - color: #666;
  907 + font-size: 24rpx;
  908 + color: #606266;
909 909 margin-top: 4rpx;
910 910 }
911 911 </style>
... ...
pages/login/index.vue
... ... @@ -14,7 +14,7 @@
14 14 line-width="55"
15 15 line-height="2"
16 16 @change="handleTabChange"
17   - :activeStyle="{ color: '#3c9cff', fontWeight:'500', fontSize: '14px' }"
  17 + :activeStyle="{ color: '#2563EB', fontWeight:'500', fontSize: '14px' }"
18 18 :inactiveStyle="{ color: '#606060', fontSize: '14px' }"
19 19 ></up-tabs>
20 20  
... ... @@ -553,7 +553,7 @@ onMounted(() =&gt; {
553 553  
554 554 :deep(.u-checkbox) {
555 555 font-size: 12px;
556   - color: #666;
  556 + color: #606266;
557 557 justify-content: flex-end;
558 558 margin-left: 0 !important;
559 559  
... ... @@ -579,7 +579,7 @@ onMounted(() =&gt; {
579 579 width: 100%;
580 580 text-align: center;
581 581 font-size: 12px;
582   - color: #999;
  582 + color: #909399;
583 583 position: fixed;
584 584 bottom: 60px;
585 585 }
... ...
pages/mine/index.vue
1 1 <template>
2 2 <view class="page-container">
3   - <!-- 顶部用户信息栏 -->
  3 + <!-- 顶部用户信息栏:品牌渐变(设计稿 --grad-head) -->
4 4 <view class="header-bg">
5 5 <up-avatar
6 6 :src="'https://img.jichengshanshui.com.cn:28207/appimg/default-avatar.png'"
7 7 size="100rpx"
8   - shape="square"
  8 + shape="circle"
9 9 class="user-avatar"
10 10 ></up-avatar>
11 11  
12   - <!-- 用户名+手机号 -->
  12 + <!-- 用户名+最近登录时间 -->
13 13 <view class="user-info-content">
14 14 <view class="user-name">{{ userStore.isLogin ? userInfo.nickname : '未登录' }}</view>
15   -<!-- <view class="user-phone">{{ userStore.isLogin ? userInfo.nickname : '&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;' }}</view>-->
16 15 <view class="user-phone">上次登录时间 {{ timeFormat(userInfo.loginDate)}}</view>
17   -
18 16 </view>
19   -
20 17 </view>
21 18  
22 19  
23 20 <view class="mine-content">
24   - <up-cell-group title="个人信息">
  21 + <view class="card-title">个人信息</view>
  22 + <up-cell-group>
25 23 <up-cell title="姓名" :value="userInfo.nickname"></up-cell>
26 24 <up-cell title="账号" :value="userInfo.username"></up-cell>
27 25 <up-cell title="电话" :value="userInfo.mobile"></up-cell>
... ... @@ -115,63 +113,111 @@ export default {
115 113 </script>
116 114  
117 115 <style lang="scss" scoped>
  116 +/* 页面底:设计稿 --page-bg */
118 117 .page-container {
119   -
  118 + min-height: 100vh;
  119 + padding-bottom: 48rpx;
  120 + box-sizing: border-box;
  121 + background-color: #F4F6FA;
120 122 }
121 123  
  124 +/* 顶部信息栏:品牌渐变(设计稿 --grad-head) */
122 125 .header-bg {
123   - position:relative;
124   - top: 0;
125   - left: 0;
  126 + position: relative;
126 127 width: 100%;
127   - height: 220px;
128   - //height: 120px;
129   - background: url("https://img.jichengshanshui.com.cn:28207/appimg/bg.jpg") no-repeat;
130   - background-size: 100% 100%;
131   - z-index: -1;
132 128 display: flex;
133   - padding: 80px 0 0 15px;
134   -}
135   -.mine-content{
136   - margin-top: -150px;
137   - border-radius: 30px 30px 0 0;
138   - background: #fff;
  129 + align-items: center;
  130 + padding: 48rpx 32rpx 120rpx;
  131 + box-sizing: border-box;
  132 + background: linear-gradient(135deg, #1D4ED8 0%, #2563EB 60%, #3B82F6 100%);
139 133 }
140 134  
141 135 .user-avatar {
  136 + flex-shrink: 0;
  137 + border: 4rpx solid rgba(255, 255, 255, 0.35);
  138 + border-radius: 50%;
  139 + overflow: hidden;
  140 +}
  141 +
  142 +/* 个人信息卡片:白底 16rpx 圆角 + 浅投影,向上压住渐变头图 */
  143 +.mine-content {
  144 + position: relative;
  145 + z-index: 1;
  146 + margin: -80rpx 24rpx 0;
  147 + padding: 8rpx 24rpx 16rpx;
  148 + background-color: #ffffff;
  149 + border-radius: 16rpx;
  150 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
  151 +}
142 152  
  153 +/* 卡片标题:设计稿 .fgrp-title */
  154 +.card-title {
  155 + padding: 16rpx 0 8rpx;
  156 + font-size: 28rpx;
  157 + font-weight: 500;
  158 + color: #1F2937;
  159 +}
  160 +
  161 +/* 单元格:标签深色 28rpx,内容值 26rpx(设计稿 .frow / .kv) */
  162 +.mine-content :deep(.u-cell-group) {
  163 + margin: 0 !important;
  164 + border-radius: 0 !important;
  165 + background-color: transparent !important;
  166 +}
  167 +.mine-content :deep(.u-cell__body) {
  168 + padding: 24rpx 0 !important;
  169 +}
  170 +.mine-content :deep(.u-cell__title-text) {
  171 + font-size: 28rpx !important;
  172 + font-weight: 400 !important;
  173 + color: #1F2937 !important;
  174 +}
  175 +.mine-content :deep(.u-cell__value) {
  176 + font-size: 26rpx !important;
  177 + color: #4B5563 !important;
  178 +}
  179 +.mine-content :deep(.u-line) {
  180 + background-color: #EEF1F6 !important;
  181 +}
  182 +/* 卡片标题已分隔,分组顶线不需要 */
  183 +.mine-content :deep(.u-cell-group__wrapper > .u-line) {
  184 + display: none !important;
  185 +}
  186 +/* 卡片内最后一行不画分隔线 */
  187 +.mine-content :deep(.u-cell:last-child .u-line) {
  188 + display: none !important;
143 189 }
144 190  
145 191 .user-info-content {
146   - margin-left: 15px;
  192 + margin-left: 24rpx;
147 193 flex: 1;
  194 + min-width: 0;
148 195  
149 196 .user-name {
150   - font-size: 16px;
151   - font-weight: 600;
  197 + font-size: 30rpx;
  198 + font-weight: 500;
152 199 color: #ffffff;
153   - margin-bottom: 5px;
154   - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
  200 + margin-bottom: 8rpx;
  201 + text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
155 202 }
156 203  
157 204 .user-phone {
158   - font-size: 13px;
159   - color: rgba(255, 255, 255, 0.9);
  205 + font-size: 24rpx;
  206 + color: rgba(255, 255, 255, 0.85);
160 207 }
161 208 }
162 209 // 退出登录按钮
163 210 .logout-btn-wrap {
164   - margin: 80px 15px 0;
  211 + margin: 48rpx 24rpx 0;
165 212 }
166   -// 登录按钮
  213 +// 登录 / 退出按钮:品牌蓝 + 16rpx 圆角(设计稿 .btn.pri.flat)
167 214 .login-btn {
168 215 width: 100%;
169   - height: 44px;
170   - line-height: 44px;
171   - border-radius: 4px;
172   - font-size: 16px;
173   - background: #0A86F4;
174   - box-shadow: 0px 4px 6px 1px rgba(25,94,215,0.5);
175   - border-radius: 23px;
  216 + height: 88rpx !important;
  217 + line-height: 88rpx !important;
  218 + border-radius: 16rpx !important;
  219 + font-size: 30rpx;
  220 + background-color: #2563EB !important;
  221 + box-shadow: none;
176 222 }
177 223 </style>
178 224 \ No newline at end of file
... ...
pages/workbench/index.vue
... ... @@ -511,7 +511,7 @@ watch(showDataLabel, () =&gt; {
511 511 }
512 512  
513 513 .grid-text {
514   - font-size: 13px;
  514 + font-size: 14px;
515 515 color: #1C1C1C;
516 516 text-align: center;
517 517 margin-top: 5px;
... ... @@ -554,7 +554,7 @@ watch(showDataLabel, () =&gt; {
554 554 text-align: center;
555 555 padding: 60px 0;
556 556 font-size: 14px;
557   - color: #999;
  557 + color: #909399;
558 558 }
559 559  
560 560 /* 图表+图例 左右布局核心样式 */
... ... @@ -603,8 +603,8 @@ watch(showDataLabel, () =&gt; {
603 603 }
604 604  
605 605 .legend-text {
606   - font-size: 13px;
607   - color: #333;
  606 + font-size: 14px;
  607 + color: #1a1a1a;
608 608 /* 单行 + 溢出省略 */
609 609 flex: 1;
610 610 white-space: nowrap;
... ... @@ -638,7 +638,7 @@ watch(showDataLabel, () =&gt; {
638 638 .table-col {
639 639 flex: 1;
640 640 text-align: center;
641   - font-size: 13px;
  641 + font-size: 14px;
642 642 display: flex;
643 643 align-items: center;
644 644 justify-content: center;
... ...
uni.scss
1 1 /* uni.scss */
2   -@import '@/uni_modules/uview-plus/theme.scss';
3 2 \ No newline at end of file
  3 +@import '@/uni_modules/uview-plus/theme.scss';
  4 +
  5 +/* ==========================================================================
  6 + * 主题色对齐 UI 规范(jcss-mp-design)
  7 + * theme.scss 中的变量没有 !default,必须在本文件 import 之后覆盖才生效。
  8 + * 只调整颜色变量,不改动任何组件默认行为。
  9 + * ========================================================================== */
  10 +$u-primary: #2563EB;
  11 +$u-primary-dark: #1D4ED8;
  12 +$u-primary-disabled: #93B4F5;
  13 +$u-primary-light: #EBF3FF;
  14 +
  15 +$u-success: #16A34A;
  16 +$u-success-dark: #12833C;
  17 +$u-success-disabled: #8ACCA2;
  18 +$u-success-light: #EAF7EF;
  19 +
  20 +$u-warning: #D97706;
  21 +$u-warning-dark: #B96504;
  22 +$u-warning-disabled: #EBBE86;
  23 +$u-warning-light: #FDF4E7;
  24 +
  25 +$u-error: #DC2626;
  26 +$u-error-dark: #B91C1C;
  27 +$u-error-disabled: #EB9A9A;
  28 +$u-error-light: #FDECEC;
  29 +
  30 +$u-info: #6B7280;
  31 +$u-info-dark: #565E6B;
  32 +$u-info-disabled: #B7BCC4;
  33 +$u-info-light: #F4F5F7;
... ...