Commit e93ebf16844c57f43863d727121a91fdc431c7f3

Authored by 王彪总
1 parent 5902ef3e

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

Showing 53 changed files with 5068 additions and 2014 deletions
@@ -44,7 +44,7 @@ const checkLoginStatus = () => { @@ -44,7 +44,7 @@ const checkLoginStatus = () => {
44 44
45 /* 你的全局样式 */ 45 /* 你的全局样式 */
46 page { 46 page {
47 - background-color: #f8f8f8; 47 + background-color: #F4F6FA;
48 height: 100%; 48 height: 100%;
49 } 49 }
50 50
@@ -57,9 +57,9 @@ page { @@ -57,9 +57,9 @@ page {
57 width: 100%; 57 width: 100%;
58 .common-name{ 58 .common-name{
59 flex: 1; // 占满剩余空间,挤压标签到右侧 59 flex: 1; // 占满剩余空间,挤压标签到右侧
60 - font-size: 28rpx; 60 + font-size: 32rpx;
61 font-weight: 500; 61 font-weight: 500;
62 - color: #333; 62 + color: #1F2937;
63 // 关键:单行文本溢出省略 63 // 关键:单行文本溢出省略
64 white-space: nowrap; 64 white-space: nowrap;
65 overflow: hidden; 65 overflow: hidden;
@@ -69,13 +69,13 @@ page { @@ -69,13 +69,13 @@ page {
69 } 69 }
70 // 已失效标签样式 70 // 已失效标签样式
71 .common-invalid-tag { 71 .common-invalid-tag {
72 - color: #f56c6c;  
73 - font-size: 24rpx; 72 + color: #6B7280;
  73 + font-size: 22rpx;
74 flex-shrink: 0; // 禁止标签被压缩 74 flex-shrink: 0; // 禁止标签被压缩
75 } 75 }
76 .common-finish-tag{ 76 .common-finish-tag{
77 - color: #5ac725;  
78 - font-size: 24rpx; 77 + color: #16A34A;
  78 + font-size: 22rpx;
79 flex-shrink: 0; // 禁止标签被压缩 79 flex-shrink: 0; // 禁止标签被压缩
80 } 80 }
81 } 81 }
@@ -84,7 +84,7 @@ page { @@ -84,7 +84,7 @@ page {
84 } 84 }
85 85
86 .u-body-item { 86 .u-body-item {
87 - margin-bottom: 16rpx; 87 + margin-bottom: 6rpx;
88 &:last-child { 88 &:last-child {
89 margin-bottom: 0; 89 margin-bottom: 0;
90 } 90 }
@@ -107,17 +107,44 @@ page { @@ -107,17 +107,44 @@ page {
107 107
108 108
109 // 底部按钮样式 109 // 底部按钮样式
  110 +// 底部固定操作栏:全站统一(白底 + 阴影 + 安全区 + 24rpx 左右留白)
110 .fixed-bottom-btn-wrap { 111 .fixed-bottom-btn-wrap {
111 position: fixed; 112 position: fixed;
112 bottom: 0; 113 bottom: 0;
113 left: 0; 114 left: 0;
114 right: 0; 115 right: 0;
115 z-index: 999; 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 .commonPageLRpadding{ 149 .commonPageLRpadding{
123 padding-left: 15px; 150 padding-left: 15px;
@@ -125,8 +152,8 @@ page { @@ -125,8 +152,8 @@ page {
125 } 152 }
126 153
127 .common-text-color{ 154 .common-text-color{
128 - font-size: 14px;  
129 - color: #606266 155 + font-size: 26rpx;
  156 + color: #4B5563
130 } 157 }
131 158
132 // 通用按钮样式(支持任意top值,无需批量生成类名) 159 // 通用按钮样式(支持任意top值,无需批量生成类名)
@@ -136,7 +163,7 @@ page { @@ -136,7 +163,7 @@ page {
136 top: var(--btn-top, 100px); 163 top: var(--btn-top, 100px);
137 right: 15px; 164 right: 15px;
138 //transform: translateX(-50%); 165 //transform: translateX(-50%);
139 - background-color: #3c9cff; 166 + background-color: #2563EB;
140 color: #ffffff; 167 color: #ffffff;
141 border: none; 168 border: none;
142 border-radius: 4px; 169 border-radius: 4px;
@@ -150,20 +177,20 @@ page { @@ -150,20 +177,20 @@ page {
150 177
151 // 点击态 178 // 点击态
152 &:active { 179 &:active {
153 - background-color: #2b88ee; 180 + background-color: #1D4ED8;
154 opacity: 0.9; 181 opacity: 0.9;
155 } 182 }
156 183
157 // 禁用态 184 // 禁用态
158 &.disabled { 185 &.disabled {
159 - background-color: #a0c8f5; 186 + background-color: #93B4F5;
160 cursor: not-allowed; 187 cursor: not-allowed;
161 opacity: 0.7; 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 </style> 196 </style>
170 \ No newline at end of file 197 \ No newline at end of file
api/maintain-manage/maintain-manage.js
@@ -83,7 +83,8 @@ export const maintainPlan= (params) =&gt; { @@ -83,7 +83,8 @@ export const maintainPlan= (params) =&gt; {
83 * @returns {Promise} 83 * @returns {Promise}
84 */ 84 */
85 export const maintainPlanNum= (params) => { 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,12 +2,12 @@
2 const env = { 2 const env = {
3 // 开发环境 3 // 开发环境
4 development: { 4 development: {
5 - baseUrl: 'https://test.jichengshanshui.com.cn:28302', 5 + // baseUrl: 'https://test.jichengshanshui.com.cn:28302',
6 // https://test.jichengshanshui.com.cn:28302 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 // baseApi:'admin-api', 11 // baseApi:'admin-api',
12 // appApi:'app-api' 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,7 +105,14 @@ export const buzStatusMap = {
105 * 工作流节点动作按钮颜色(与统一动作弹窗保持一致) 105 * 工作流节点动作按钮颜色(与统一动作弹窗保持一致)
106 * @param {string} code - 动作编码,如 ASSIGN/REJECT/RETURN_PREV 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 switch (code) { 116 switch (code) {
110 case 'APPROVE': 117 case 'APPROVE':
111 case 'HANDLE': 118 case 'HANDLE':
@@ -124,6 +131,17 @@ export const getActionButtonType = (code) =&gt; { @@ -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 * @param {string | Date | number} startTime - 开始时间(时间字符串/Date对象/10位/13位时间戳) 146 * @param {string | Date | number} startTime - 开始时间(时间字符串/Date对象/10位/13位时间戳)
129 * @param {string | Date | number} endTime - 结束时间(时间字符串/Date对象/10位/13位时间戳) 147 * @param {string | Date | number} endTime - 结束时间(时间字符串/Date对象/10位/13位时间戳)
components/grouped-picker/grouped-picker.vue
@@ -35,8 +35,8 @@ @@ -35,8 +35,8 @@
35 @change="onTabChange" 35 @change="onTabChange"
36 :lineWidth="30" 36 :lineWidth="30"
37 :lineHeight="4" 37 :lineHeight="4"
38 - activeColor="#2979ff"  
39 - lineColor="#2979ff" 38 + activeColor="#2563EB"
  39 + lineColor="#2563EB"
40 inactiveColor="#606266" 40 inactiveColor="#606266"
41 > 41 >
42 </up-tabs> 42 </up-tabs>
@@ -92,7 +92,7 @@ @@ -92,7 +92,7 @@
92 </view> 92 </view>
93 <!-- 单选:原型没覆盖,右侧给一个选中标记 --> 93 <!-- 单选:原型没覆盖,右侧给一个选中标记 -->
94 <view v-else-if="!multiple" class="gp-radio"> 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 </view> 96 </view>
97 </view> 97 </view>
98 </view> 98 </view>
@@ -487,9 +487,9 @@ watch( @@ -487,9 +487,9 @@ watch(
487 height: 28rpx; 487 height: 28rpx;
488 padding: 0 6rpx; 488 padding: 0 6rpx;
489 border-radius: 14rpx; 489 border-radius: 14rpx;
490 - background: #2979ff; 490 + background: #2563EB;
491 color: #ffffff; 491 color: #ffffff;
492 - font-size: 20rpx; 492 + font-size: 24rpx;
493 line-height: 28rpx; 493 line-height: 28rpx;
494 text-align: center; 494 text-align: center;
495 } 495 }
@@ -537,8 +537,8 @@ watch( @@ -537,8 +537,8 @@ watch(
537 justify-content: center; 537 justify-content: center;
538 538
539 &.is-checked { 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,7 +562,7 @@ watch(
562 562
563 .gp-row-crumb { 563 .gp-row-crumb {
564 margin-top: 4rpx; 564 margin-top: 4rpx;
565 - font-size: 22rpx; 565 + font-size: 24rpx;
566 color: #909399; 566 color: #909399;
567 } 567 }
568 568
@@ -609,7 +609,7 @@ watch( @@ -609,7 +609,7 @@ watch(
609 609
610 .gp-empty { 610 .gp-empty {
611 padding: 60rpx 0; 611 padding: 60rpx 0;
612 - font-size: 26rpx; 612 + font-size: 28rpx;
613 color: #c0c4cc; 613 color: #c0c4cc;
614 text-align: center; 614 text-align: center;
615 } 615 }
components/my-cascader/my-cascader.vue
@@ -337,10 +337,10 @@ onMounted(() =&gt; { @@ -337,10 +337,10 @@ onMounted(() =&gt; {
337 } 337 }
338 .trigger-text { 338 .trigger-text {
339 font-size: 28rpx; 339 font-size: 28rpx;
340 - color: #333; 340 + color: #1a1a1a;
341 } 341 }
342 .trigger-icon { 342 .trigger-icon {
343 - color: #999; 343 + color: #909399;
344 } 344 }
345 345
346 .area-box { 346 .area-box {
components/unified-task-actions/unified-task-actions.vue
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 mode="bottom" 4 mode="bottom"
5 round 5 round
6 closeable 6 closeable
  7 + bg-color="#F4F6FA"
7 :safe-area-inset-bottom="true" 8 :safe-area-inset-bottom="true"
8 @close="close" 9 @close="close"
9 > 10 >
@@ -15,7 +16,7 @@ @@ -15,7 +16,7 @@
15 <up-button 16 <up-button
16 v-for="action in actions" 17 v-for="action in actions"
17 :key="action.code" 18 :key="action.code"
18 - :type="getButtonType(action.code)" 19 + :type="getButtonType(action.code, action.name)"
19 size="large" 20 size="large"
20 :customStyle="{ marginBottom: '20rpx' }" 21 :customStyle="{ marginBottom: '20rpx' }"
21 @click="selectAction(action)" 22 @click="selectAction(action)"
@@ -28,7 +29,10 @@ @@ -28,7 +29,10 @@
28 <!-- 第二步:动作表单 --> 29 <!-- 第二步:动作表单 -->
29 <view v-else class="unified-action-form"> 30 <view v-else class="unified-action-form">
30 <view v-if="current.requireAssignee" class="form-item"> 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 <up-radio-group v-if="workers.length" v-model="form.nextAssignee" class="worker-list"> 36 <up-radio-group v-if="workers.length" v-model="form.nextAssignee" class="worker-list">
33 <up-radio 37 <up-radio
34 v-for="worker in workers" 38 v-for="worker in workers"
@@ -43,7 +47,10 @@ @@ -43,7 +47,10 @@
43 </view> 47 </view>
44 48
45 <view class="form-item"> 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 <up-textarea 54 <up-textarea
48 v-model.trim="form.reason" 55 v-model.trim="form.reason"
49 :placeholder="reasonPlaceholder" 56 :placeholder="reasonPlaceholder"
@@ -54,7 +61,10 @@ @@ -54,7 +61,10 @@
54 </view> 61 </view>
55 62
56 <view v-if="current.requireAttachment" class="form-item"> 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 <up-upload 68 <up-upload
59 :file-list="attachImgs.rawImgList.value || []" 69 :file-list="attachImgs.rawImgList.value || []"
60 @after-read="attachImgs.uploadImgs" 70 @after-read="attachImgs.uploadImgs"
@@ -181,8 +191,12 @@ const backToList = () =&gt; { @@ -181,8 +191,12 @@ const backToList = () =&gt; {
181 current.value = null 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 switch (code) { 200 switch (code) {
187 case 'APPROVE': 201 case 'APPROVE':
188 case 'HANDLE': 202 case 'HANDLE':
@@ -285,17 +299,20 @@ defineExpose({ open }) @@ -285,17 +299,20 @@ defineExpose({ open })
285 </script> 299 </script>
286 300
287 <style lang="scss" scoped> 301 <style lang="scss" scoped>
  302 +// 弹窗内容:浅灰底(由 up-popup 的 bg-color 控制),左右 24rpx
288 .unified-action-popup { 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 max-height: 80vh; 305 max-height: 80vh;
291 overflow-y: auto; 306 overflow-y: auto;
  307 + box-sizing: border-box;
292 } 308 }
293 309
294 .unified-action-title { 310 .unified-action-title {
295 - font-size: 34rpx;  
296 - font-weight: bold; 311 + font-size: 32rpx;
  312 + font-weight: 500;
  313 + color: #1F2937;
297 text-align: center; 314 text-align: center;
298 - margin-bottom: 40rpx; 315 + margin-bottom: 24rpx;
299 } 316 }
300 317
301 .unified-action-list { 318 .unified-action-list {
@@ -304,34 +321,103 @@ defineExpose({ open }) @@ -304,34 +321,103 @@ defineExpose({ open })
304 } 321 }
305 322
306 .unified-action-tip { 323 .unified-action-tip {
307 - color: #909399;  
308 - font-size: 26rpx; 324 + color: #9CA3AF;
  325 + font-size: 28rpx;
309 padding: 20rpx 0; 326 padding: 20rpx 0;
310 } 327 }
311 328
  329 +// 表单分区:白色卡片(设计稿 .card)
312 .unified-action-form .form-item { 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 .form-label { 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 .worker-list { 361 .worker-list {
323 display: flex; 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 .unified-action-btns { 401 .unified-action-btns {
329 display: flex; 402 display: flex;
330 gap: 24rpx; 403 gap: 24rpx;
331 - margin-top: 20rpx; 404 + margin-top: 32rpx;
332 405
333 ::v-deep .u-button { 406 ::v-deep .u-button {
334 flex: 1; 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 </style> 423 </style>
components/work-field-form/work-field-form.vue
@@ -798,7 +798,7 @@ export default { @@ -798,7 +798,7 @@ export default {
798 :deep(.u-number-box__input) { 798 :deep(.u-number-box__input) {
799 width: 264rpx !important; 799 width: 264rpx !important;
800 height: 72rpx; 800 height: 72rpx;
801 - font-size: 32rpx; 801 + font-size: 30rpx;
802 } 802 }
803 803
804 :deep(.u-number-box__btn) { 804 :deep(.u-number-box__btn) {
@@ -819,7 +819,7 @@ export default { @@ -819,7 +819,7 @@ export default {
819 819
820 .unit-text { 820 .unit-text {
821 font-size: 28rpx; 821 font-size: 28rpx;
822 - color: #333; 822 + color: #1a1a1a;
823 } 823 }
824 } 824 }
825 825
@@ -853,7 +853,7 @@ export default { @@ -853,7 +853,7 @@ export default {
853 flex: 1; 853 flex: 1;
854 min-width: 0; 854 min-width: 0;
855 font-size: 28rpx; 855 font-size: 28rpx;
856 - color: #333; 856 + color: #1a1a1a;
857 } 857 }
858 } 858 }
859 859
@@ -878,14 +878,14 @@ export default { @@ -878,14 +878,14 @@ export default {
878 flex: 1; 878 flex: 1;
879 min-width: 0; 879 min-width: 0;
880 font-size: 28rpx; 880 font-size: 28rpx;
881 - color: #333; 881 + color: #1a1a1a;
882 overflow: hidden; 882 overflow: hidden;
883 white-space: nowrap; 883 white-space: nowrap;
884 text-overflow: ellipsis; 884 text-overflow: ellipsis;
885 } 885 }
886 886
887 .file-del { 887 .file-del {
888 - font-size: 26rpx; 888 + font-size: 28rpx;
889 color: #ff4d4f; 889 color: #ff4d4f;
890 } 890 }
891 } 891 }
pages-sub/daily/attendanceRecord.vue
@@ -254,17 +254,19 @@ onMounted(async () =&gt; { @@ -254,17 +254,19 @@ onMounted(async () =&gt; {
254 </script> 254 </script>
255 <style scoped lang="scss"> 255 <style scoped lang="scss">
256 .attendance-page { 256 .attendance-page {
257 - padding: 20rpx;  
258 - background-color: #f5f5f7; 257 + padding: 24rpx;
  258 + background-color: #F4F6FA;
259 min-height: 100vh; 259 min-height: 100vh;
  260 + box-sizing: border-box;
260 } 261 }
261 262
262 .stat-card { 263 .stat-card {
263 display: flex; 264 display: flex;
264 - background-color: #3c9cff; 265 + background-color: #2563EB;
265 border-radius: 16rpx; 266 border-radius: 16rpx;
266 padding: 30rpx 0; 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 .stat-item { 271 .stat-item {
270 flex: 1; 272 flex: 1;
@@ -285,10 +287,11 @@ onMounted(async () =&gt; { @@ -285,10 +287,11 @@ onMounted(async () =&gt; {
285 } 287 }
286 288
287 .calendar-wrap { 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 .calendar-header { 297 .calendar-header {
@@ -299,7 +302,7 @@ onMounted(async () =&gt; { @@ -299,7 +302,7 @@ onMounted(async () =&gt; {
299 } 302 }
300 303
301 .calendar-title { 304 .calendar-title {
302 - font-size: 32rpx; 305 + font-size: 30rpx;
303 font-weight: bold; 306 font-weight: bold;
304 } 307 }
305 308
@@ -307,7 +310,7 @@ onMounted(async () =&gt; { @@ -307,7 +310,7 @@ onMounted(async () =&gt; {
307 padding: 8rpx 16rpx; 310 padding: 8rpx 16rpx;
308 border: 1rpx solid #eee; 311 border: 1rpx solid #eee;
309 border-radius: 8rpx; 312 border-radius: 8rpx;
310 - font-size: 26rpx; 313 + font-size: 28rpx;
311 } 314 }
312 315
313 .empty-btn { 316 .empty-btn {
@@ -321,8 +324,8 @@ onMounted(async () =&gt; { @@ -321,8 +324,8 @@ onMounted(async () =&gt; {
321 .week-item { 324 .week-item {
322 flex: 1; 325 flex: 1;
323 text-align: center; 326 text-align: center;
324 - font-size: 26rpx;  
325 - color: #666; 327 + font-size: 28rpx;
  328 + color: #606266;
326 padding: 10rpx 0; 329 padding: 10rpx 0;
327 } 330 }
328 } 331 }
@@ -363,13 +366,14 @@ onMounted(async () =&gt; { @@ -363,13 +366,14 @@ onMounted(async () =&gt; {
363 } 366 }
364 367
365 .detail-card { 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 .empty-text { 374 .empty-text {
371 text-align: center; 375 text-align: center;
372 - color: #999; 376 + color: #909399;
373 font-size: 30rpx; 377 font-size: 30rpx;
374 padding: 40rpx 0; 378 padding: 40rpx 0;
375 } 379 }
@@ -380,14 +384,14 @@ onMounted(async () =&gt; { @@ -380,14 +384,14 @@ onMounted(async () =&gt; {
380 384
381 .detail-title { 385 .detail-title {
382 font-size: 30rpx; 386 font-size: 30rpx;
383 - color: #333; 387 + color: #1a1a1a;
384 width: 220rpx; 388 width: 220rpx;
385 } 389 }
386 390
387 .detail-text { 391 .detail-text {
388 flex: 1; 392 flex: 1;
389 font-size: 30rpx; 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 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 <view class="inspect-form-content commonPageLRpadding" ref="formContentRef"> 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 <template v-for="item in dynamicFields" :key="item.fieldCode"> 11 <template v-for="item in dynamicFields" :key="item.fieldCode">
7 <up-form-item :label="item.fieldName" :prop="item.fieldCode" class="form-item" 12 <up-form-item :label="item.fieldName" :prop="item.fieldCode" class="form-item"
@@ -129,6 +134,10 @@ @@ -129,6 +134,10 @@
129 <view v-if="dynamicFields.length === 0" class="empty-field-tip"> 134 <view v-if="dynamicFields.length === 0" class="empty-field-tip">
130 <text>请去平台配置业务类型字段</text> 135 <text>请去平台配置业务类型字段</text>
131 </view> 136 </view>
  137 + <!-- 提交说明(设计稿底部注释文案) -->
  138 + <view class="submit-hint" v-if="dynamicFields.length > 0">
  139 + 【提交】仅记录本次作业,后续还可再次提交;【提交并结束本次任务】作业全部完成,无须再上报
  140 + </view>
132 <view class="fixed-bottom-btn-wrap" v-if="dynamicFields.length > 0"> 141 <view class="fixed-bottom-btn-wrap" v-if="dynamicFields.length > 0">
133 <view class="btn-item btn-left" @click="submitInspect"> 142 <view class="btn-item btn-left" @click="submitInspect">
134 <text>提交</text> 143 <text>提交</text>
@@ -1077,14 +1086,78 @@ export default { @@ -1077,14 +1086,78 @@ export default {
1077 </script> 1086 </script>
1078 1087
1079 <style lang="scss" scoped> 1088 <style lang="scss" scoped>
  1089 +// 页面:设计稿底 #F4F6FA,底部给固定操作栏留位(按钮 88rpx + 上下 24rpx)
1080 .page-container { 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 .inspect-form-content { 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 .date-input-wrap { 1163 .date-input-wrap {
@@ -1096,7 +1169,7 @@ export default { @@ -1096,7 +1169,7 @@ export default {
1096 :deep(.u-number-box__input) { 1169 :deep(.u-number-box__input) {
1097 width: 264rpx !important; 1170 width: 264rpx !important;
1098 height: 72rpx; 1171 height: 72rpx;
1099 - font-size: 32rpx; 1172 + font-size: 30rpx;
1100 } 1173 }
1101 1174
1102 :deep(.u-number-box__btn) { 1175 :deep(.u-number-box__btn) {
@@ -1117,7 +1190,7 @@ export default { @@ -1117,7 +1190,7 @@ export default {
1117 1190
1118 .unit-text { 1191 .unit-text {
1119 font-size: 28rpx; 1192 font-size: 28rpx;
1120 - color: #333; 1193 + color: #1a1a1a;
1121 } 1194 }
1122 } 1195 }
1123 1196
@@ -1151,7 +1224,7 @@ export default { @@ -1151,7 +1224,7 @@ export default {
1151 flex: 1; 1224 flex: 1;
1152 min-width: 0; 1225 min-width: 0;
1153 font-size: 28rpx; 1226 font-size: 28rpx;
1154 - color: #333; 1227 + color: #1a1a1a;
1155 } 1228 }
1156 } 1229 }
1157 1230
@@ -1176,59 +1249,78 @@ export default { @@ -1176,59 +1249,78 @@ export default {
1176 flex: 1; 1249 flex: 1;
1177 min-width: 0; 1250 min-width: 0;
1178 font-size: 28rpx; 1251 font-size: 28rpx;
1179 - color: #333; 1252 + color: #1a1a1a;
1180 overflow: hidden; 1253 overflow: hidden;
1181 white-space: nowrap; 1254 white-space: nowrap;
1182 text-overflow: ellipsis; 1255 text-overflow: ellipsis;
1183 } 1256 }
1184 1257
1185 .file-del { 1258 .file-del {
1186 - font-size: 26rpx; 1259 + font-size: 28rpx;
1187 color: #ff4d4f; 1260 color: #ff4d4f;
1188 } 1261 }
1189 } 1262 }
1190 } 1263 }
1191 1264
  1265 +// 无字段配置提示:与表单卡同宽同圆角
1192 .empty-field-tip { 1266 .empty-field-tip {
1193 - padding: 80rpx 30rpx; 1267 + margin: 0 24rpx;
  1268 + padding: 80rpx 24rpx;
1194 text-align: center; 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 .fixed-bottom-btn-wrap { 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 display: flex; 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 .btn-item { 1301 .btn-item {
1203 flex: 1; 1302 flex: 1;
1204 height: 88rpx; 1303 height: 88rpx;
1205 -  
1206 display: flex; 1304 display: flex;
1207 align-items: center; 1305 align-items: center;
1208 justify-content: center; 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 .btn-left { 1312 .btn-left {
1214 - background: #1989fa; 1313 + background-color: #ffffff;
  1314 + border: 1rpx solid #E8EBF0;
  1315 + color: #1F2937;
1215 } 1316 }
1216 1317
1217 .btn-right { 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 </style> 1326 </style>
pages-sub/daily/maintain-manage/finish-plan-detail.vue
@@ -5,41 +5,40 @@ @@ -5,41 +5,40 @@
5 v-if="loading" 5 v-if="loading"
6 :loading="true" 6 :loading="true"
7 title="加载中..." 7 title="加载中..."
8 - color="#3c9cff" 8 + color="#2563EB"
9 ></up-loading-page> 9 ></up-loading-page>
10 10
11 <!-- 内容容器 --> 11 <!-- 内容容器 -->
12 <template v-else> 12 <template v-else>
13 <view class="content-wrap" v-for="(i, index) in orderDetail" :key="index"> 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 <!-- 2. 工单位置 --> 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 <!-- 4. 情况描述 --> 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 <!-- 5. 问题照片(核心修复:兼容WebP + 强制尺寸) --> 43 <!-- 5. 问题照片(核心修复:兼容WebP + 强制尺寸) -->
45 <!-- <up-cell title="照片"> 44 <!-- <up-cell title="照片">
@@ -87,38 +86,31 @@ @@ -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 <!-- 动态配置的养护字段填报值(garden_work_record/garden_work_field_value),未填报过则整段不显示 --> 100 <!-- 动态配置的养护字段填报值(garden_work_record/garden_work_field_value),未填报过则整段不显示 -->
105 <!-- 动态配置的养护字段填报值(garden_work_record/garden_work_field_value),未填报过则整段不显示 --> 101 <!-- 动态配置的养护字段填报值(garden_work_record/garden_work_field_value),未填报过则整段不显示 -->
106 -<up-cell-group 102 +<view
  103 + class="form-card"
107 v-if="i.fieldRows && i.fieldRows.length" 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 <!-- 7 图片:复用本页照片的相册组件(预览/尺寸一致) --> 114 <!-- 7 图片:复用本页照片的相册组件(预览/尺寸一致) -->
123 <up-album 115 <up-album
124 v-if="f.kind === 'image'" 116 v-if="f.kind === 'image'"
@@ -146,9 +138,9 @@ @@ -146,9 +138,9 @@
146 <text v-else-if="f.kind === 'geo' && f.geo" class="field-link" @click="openGeo(f.geo)">{{ f.text }}</text> 138 <text v-else-if="f.kind === 'geo' && f.geo" class="field-link" @click="openGeo(f.geo)">{{ f.text }}</text>
147 <!-- 其余(1数值/2文本/3单选枚举/4日期/5布尔等)文本直出 --> 139 <!-- 其余(1数值/2文本/3单选枚举/4日期/5布尔等)文本直出 -->
148 <text v-else class="common-text-color field-text">{{ f.text }}</text> 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 <view v-else class="no-record-tip"> 145 <view v-else class="no-record-tip">
154 直接结束了本次任务 146 直接结束了本次任务
@@ -552,12 +544,85 @@ onLoad((options) =&gt; { @@ -552,12 +544,85 @@ onLoad((options) =&gt; {
552 </script> 544 </script>
553 545
554 <style scoped lang="scss"> 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 .content-wrap { 555 .content-wrap {
557 - background: #fff; 556 + background: transparent;
558 width: 100%; 557 width: 100%;
559 box-sizing: border-box; 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,7 +654,7 @@ onLoad((options) =&gt; {
589 654
590 // 空文本样式 655 // 空文本样式
591 .empty-text { 656 .empty-text {
592 - color: #999; 657 + color: #909399;
593 font-size: 14px; 658 font-size: 14px;
594 line-height: 70px; // 和图片高度对齐 659 line-height: 70px; // 和图片高度对齐
595 } 660 }
@@ -605,17 +670,17 @@ onLoad((options) =&gt; { @@ -605,17 +670,17 @@ onLoad((options) =&gt; {
605 670
606 // 自绘标签:仓库未使用过 up-tag,避免引入未验证组件 671 // 自绘标签:仓库未使用过 up-tag,避免引入未验证组件
607 .field-tag { 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 .field-file { 682 .field-file {
618 - color: #3c9cff; 683 + color: #2563EB;
619 font-size: 26rpx; 684 font-size: 26rpx;
620 margin-left: 16rpx; 685 margin-left: 16rpx;
621 text-decoration: underline; 686 text-decoration: underline;
@@ -623,7 +688,7 @@ onLoad((options) =&gt; { @@ -623,7 +688,7 @@ onLoad((options) =&gt; {
623 688
624 // 链接 / 地理位置(可点击) 689 // 链接 / 地理位置(可点击)
625 .field-link { 690 .field-link {
626 - color: #3c9cff; 691 + color: #2563EB;
627 font-size: 26rpx; 692 font-size: 26rpx;
628 word-break: break-all; 693 word-break: break-all;
629 } 694 }
@@ -637,10 +702,15 @@ onLoad((options) =&gt; { @@ -637,10 +702,15 @@ onLoad((options) =&gt; {
637 min-width: 160rpx; // 固定左侧标题最大宽度,文字会在这个宽度内自动换行 702 min-width: 160rpx; // 固定左侧标题最大宽度,文字会在这个宽度内自动换行
638 } 703 }
639 704
  705 +// 无填报记录提示:与上方信息卡同宽同圆角
640 .no-record-tip { 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 +8,8 @@
8 v-model="activeType" 8 v-model="activeType"
9 :list="typeTabs" 9 :list="typeTabs"
10 line-width="40rpx" 10 line-width="40rpx"
11 - active-color="#1989fa"  
12 - inactive-color="#666" 11 + active-color="#2563EB"
  12 + inactive-color="#606266"
13 :scrollable="true" 13 :scrollable="true"
14 class="first-tabs" 14 class="first-tabs"
15 @click="handleTypeChange" 15 @click="handleTypeChange"
@@ -20,8 +20,8 @@ @@ -20,8 +20,8 @@
20 v-model="activeStatus" 20 v-model="activeStatus"
21 :list="statusTabs" 21 :list="statusTabs"
22 line-width="40rpx" 22 line-width="40rpx"
23 - active-color="#1989fa"  
24 - inactive-color="#666" 23 + active-color="#2563EB"
  24 + inactive-color="#606266"
25 :scrollable="true" 25 :scrollable="true"
26 class="second-tabs" 26 class="second-tabs"
27 @click="handleStatusChange" 27 @click="handleStatusChange"
@@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
40 @custom="handleSearch" 40 @custom="handleSearch"
41 :clearabled="false" 41 :clearabled="false"
42 maxlength="50" 42 maxlength="50"
43 - style="margin: 0rpx 20rpx 0" 43 + style="margin: 0rpx 24rpx 0"
44 ></up-search> 44 ></up-search>
45 </view> 45 </view>
46 </up-sticky> 46 </up-sticky>
@@ -58,32 +58,28 @@ @@ -58,32 +58,28 @@
58 </template> 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 <up-card 63 <up-card
64 :border="false" 64 :border="false"
65 :foot-border-top="false" 65 :foot-border-top="false"
66 :head-border-bottom="false" 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 v-for="(item,index) in currentList" 71 v-for="(item,index) in currentList"
68 :key="`${item.planNo}_${index}`" 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 <template #body> 81 <template #body>
72 <view class="card-body"> 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 <!-- <view class="u-body-item u-flex">--> 83 <!-- <view class="u-body-item u-flex">-->
88 <!-- <view class="u-body-item-title">批次号:</view>--> 84 <!-- <view class="u-body-item-title">批次号:</view>-->
89 <!-- <view class="u-line-1 u-body-value">{{ item.batchNo || '-' }}</view>--> 85 <!-- <view class="u-line-1 u-body-value">{{ item.batchNo || '-' }}</view>-->
@@ -105,14 +101,18 @@ @@ -105,14 +101,18 @@
105 </view> --> 101 </view> -->
106 102
107 <view class="u-body-item u-flex"> 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 </view> 116 </view>
117 117
118 <!-- <view class="u-body-item u-flex">--> 118 <!-- <view class="u-body-item u-flex">-->
@@ -127,11 +127,16 @@ @@ -127,11 +127,16 @@
127 </view> 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 <up-card 132 <up-card
133 :border="false" 133 :border="false"
134 :foot-border-top="false" 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 v-for="(item,index) in currentList" 140 v-for="(item,index) in currentList"
136 :key="`${item.planNo}_${index}`" 141 :key="`${item.planNo}_${index}`"
137 142
@@ -145,9 +150,6 @@ @@ -145,9 +150,6 @@
145 150
146 <template #body> 151 <template #body>
147 <view class="card-body"> 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 <view class="u-body-item u-flex"> 153 <view class="u-body-item u-flex">
152 <view class="u-body-item-title">计划编码:</view> 154 <view class="u-body-item-title">计划编码:</view>
153 <view class="u-line-1 u-body-value">{{ item.planNo || '-' }}</view> 155 <view class="u-line-1 u-body-value">{{ item.planNo || '-' }}</view>
@@ -159,18 +161,9 @@ @@ -159,18 +161,9 @@
159 </view> 161 </view>
160 </view> 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 </view> 167 </view>
175 168
176 <view class="u-body-item u-flex"> 169 <view class="u-body-item u-flex">
@@ -184,6 +177,11 @@ @@ -184,6 +177,11 @@
184 {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }} 177 {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }}
185 </view> 178 </view>
186 </view> 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 </view> 185 </view>
188 </template> 186 </template>
189 </up-card> 187 </up-card>
@@ -343,16 +341,40 @@ onShow(()=&gt;{ @@ -343,16 +341,40 @@ onShow(()=&gt;{
343 </script> 341 </script>
344 342
345 <style scoped lang="scss"> 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 .sticky-wrap { 354 .sticky-wrap {
348 background-color: #fff; 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 .first-tabs, .second-tabs { 359 .first-tabs, .second-tabs {
353 margin: 10rpx 0; 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 </style> 380 </style>
359 \ No newline at end of file 381 \ No newline at end of file
pages-sub/daily/maintain-manage/now-list-page.vue
@@ -111,32 +111,64 @@ const handleAddReport = () =&gt; { @@ -111,32 +111,64 @@ const handleAddReport = () =&gt; {
111 <style scoped lang="scss"> 111 <style scoped lang="scss">
112 .page-wrap { 112 .page-wrap {
113 min-height: 100vh; 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 .tip-bar { 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 .list-wrap { 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 .report-item { 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 .item-title { 162 .item-title {
132 font-size: 32rpx; 163 font-size: 32rpx;
133 - color: #222; 164 + color: #1F2937;
134 font-weight: 500; 165 font-weight: 500;
135 - margin-bottom: 20rpx; 166 + line-height: 1.4;
  167 + margin-bottom: 16rpx;
136 } 168 }
137 .item-row { 169 .item-row {
138 - font-size: 28rpx;  
139 - color: #555; 170 + font-size: 26rpx;
  171 + color: #4B5563;
140 margin-bottom: 12rpx; 172 margin-bottom: 12rpx;
141 } 173 }
142 .item-row-bottom { 174 .item-row-bottom {
@@ -145,20 +177,50 @@ const handleAddReport = () =&gt; { @@ -145,20 +177,50 @@ const handleAddReport = () =&gt; {
145 align-items: center; 177 align-items: center;
146 margin-bottom: 0; 178 margin-bottom: 0;
147 } 179 }
  180 + // 查看:次要操作,白底描边(设计稿 .btn 次级按钮)
148 .look-btn { 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 .empty-wrap { 197 .empty-wrap {
154 padding-top: 120rpx; 198 padding-top: 120rpx;
155 } 199 }
  200 +// 底部固定操作栏:白底 + 上分隔线 + 蓝色渐变主按钮(设计稿 .bar / .btn.pri)
156 .fixed-bottom-btn-wrap { 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 </style> 226 </style>
pages-sub/daily/maintain-manage/pending-plan-detail.vue
1 <template> 1 <template>
2 <view class="page-container"> 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 </view> 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 <view class="u-body-item u-flex"> 20 <view class="u-body-item u-flex">
37 <view class="u-body-item-title">计划编码:</view> 21 <view class="u-body-item-title">计划编码:</view>
@@ -66,22 +50,25 @@ @@ -66,22 +50,25 @@
66 {{ timeFormat(i.endTime, 'yyyy-mm-dd') || '-' }} 50 {{ timeFormat(i.endTime, 'yyyy-mm-dd') || '-' }}
67 </view> 51 </view>
68 </view> 52 </view>
  53 +
  54 + <!-- 底部操作区(分隔线 + 右对齐按钮) -->
  55 + <view class="card-action-row">
  56 + <view class="mini-btn mini-btn--primary" @click="gotoFinishPlanDetail(i)">查看记录</view>
69 </view> 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 </view> 59 </view>
84 </view> 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 </view> 72 </view>
86 </template> 73 </template>
87 74
@@ -149,7 +136,63 @@ const addNewRecord = () =&gt; { @@ -149,7 +136,63 @@ const addNewRecord = () =&gt; {
149 </script> 136 </script>
150 137
151 <style scoped lang="scss"> 138 <style scoped lang="scss">
  139 +/* 统一卡片样式(与巡查计划明细一致) */
152 .page-container { 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 </style> 198 </style>
156 \ No newline at end of file 199 \ No newline at end of file
pages-sub/daily/maintain-manage/record-detail-list.vue
@@ -5,93 +5,63 @@ @@ -5,93 +5,63 @@
5 v-if="loading" 5 v-if="loading"
6 :loading="true" 6 :loading="true"
7 title="加载中..." 7 title="加载中..."
8 - color="#3c9cff" 8 + color="#2563EB"
9 ></up-loading-page> 9 ></up-loading-page>
10 10
11 <!-- 内容容器 --> 11 <!-- 内容容器 -->
12 <view v-else class="content-wrap"> 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 </view> 67 </view>
@@ -144,48 +114,66 @@ onLoad((options) =&gt; { @@ -144,48 +114,66 @@ onLoad((options) =&gt; {
144 114
145 <style scoped lang="scss"> 115 <style scoped lang="scss">
146 // 页面基础样式 116 // 页面基础样式
  117 +.page-container,
147 .u-page { 118 .u-page {
148 min-height: 100vh; 119 min-height: 100vh;
149 - background-color: #f5f5f5; 120 + padding-bottom: 40rpx;
  121 + background-color: #F4F6FA;
150 box-sizing: border-box; 122 box-sizing: border-box;
151 } 123 }
152 124
153 // 内容容器 125 // 内容容器
154 .content-wrap { 126 .content-wrap {
155 - background: #fff; 127 + padding: 0 24rpx;
156 width: 100%; 128 width: 100%;
157 box-sizing: border-box; 129 box-sizing: border-box;
158 overflow-y: auto; 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 .empty-text { 169 .empty-text {
166 - color: #999; 170 + color: #909399;
167 font-size: 28rpx; 171 font-size: 28rpx;
168 line-height: 80rpx; 172 line-height: 80rpx;
169 display: block; 173 display: block;
170 text-align: left; 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 :deep(.up-album) { 178 :deep(.up-album) {
191 width: 100%; 179 width: 100%;
pages-sub/daily/maintain-manage/road-detail-list.vue
@@ -7,9 +7,9 @@ @@ -7,9 +7,9 @@
7 <up-tabs 7 <up-tabs
8 v-model="activeStatus" 8 v-model="activeStatus"
9 :list="statusTabs" 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 :scrollable="true" 13 :scrollable="true"
14 class="status-tabs" 14 class="status-tabs"
15 @click="handleStatusChange" 15 @click="handleStatusChange"
@@ -44,10 +44,15 @@ @@ -44,10 +44,15 @@
44 <template #empty> 44 <template #empty>
45 <empty-view/> 45 <empty-view/>
46 </template> 46 </template>
47 - <view class="common-card-list" style=" padding-top: 170rpx;"> 47 + <view class="common-card-list plan-card-list">
48 <up-card 48 <up-card
49 :border="false" 49 :border="false"
50 :foot-border-top="false" 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 v-for="(item,index) in planList" 56 v-for="(item,index) in planList"
52 :key="`${item.planNo}_${index}`" 57 :key="`${item.planNo}_${index}`"
53 > 58 >
@@ -55,6 +60,8 @@ @@ -55,6 +60,8 @@
55 <template #head> 60 <template #head>
56 <view class="card-header"> 61 <view class="card-header">
57 <view class="common-card-title common-name">{{ item.planName || '无计划名称' }}</view> 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 <view v-show="item.finishState == 3 " class="common-invalid-tag">已失效</view> 66 <view v-show="item.finishState == 3 " class="common-invalid-tag">已失效</view>
60 <view v-show="item.finishState == 2 " class="common-finish-tag">已完成</view> 67 <view v-show="item.finishState == 2 " class="common-finish-tag">已完成</view>
@@ -76,14 +83,6 @@ @@ -76,14 +83,6 @@
76 <!-- </up-button>--> 83 <!-- </up-button>-->
77 <!-- </view>--> 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 <view class="u-body-item u-flex"> 86 <view class="u-body-item u-flex">
88 <view class="u-body-item-title">计划编码:</view> 87 <view class="u-body-item-title">计划编码:</view>
89 <view class="u-line-1 u-body-value">{{ item.planNo || '-' }}</view> 88 <view class="u-line-1 u-body-value">{{ item.planNo || '-' }}</view>
@@ -95,23 +94,13 @@ @@ -95,23 +94,13 @@
95 </view> 94 </view>
96 </view> 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 </view> 100 </view>
112 101
113 <view class="u-body-item u-flex"> 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 <view class="u-line-1 u-body-value">{{ item.planFinishNum || 0 }}</view> 104 <view class="u-line-1 u-body-value">{{ item.planFinishNum || 0 }}</view>
116 </view> 105 </view>
117 106
@@ -121,6 +110,12 @@ @@ -121,6 +110,12 @@
121 {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }} 110 {{ timeFormat(item.endTime, 'yyyy-mm-dd') || '-' }}
122 </view> 111 </view>
123 </view> 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 </view> 119 </view>
125 </template> 120 </template>
126 </up-card> 121 </up-card>
@@ -221,20 +216,36 @@ onShow(() =&gt; { @@ -221,20 +216,36 @@ onShow(() =&gt; {
221 </script> 216 </script>
222 217
223 <style scoped lang="scss"> 218 <style scoped lang="scss">
  219 +/* 页面底色:统一浅灰蓝(设计稿 --page-bg) */
224 .page-container { 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 .sticky-header { 227 .sticky-header {
228 - margin-top: -10rpx;  
229 background-color: #ffffff; 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 .search-input { 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 </style> 251 </style>
241 \ No newline at end of file 252 \ No newline at end of file
pages-sub/daily/maintain-manage/type-list-page.vue
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 <view class="page-container"> 2 <view class="page-container">
3 <up-sticky> 3 <up-sticky>
4 <view class="sticky-wrap"> 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 </view> 7 </view>
8 </up-sticky> 8 </up-sticky>
9 <z-paging ref="pagingRef" v-model="currentList" @query="fetchData" :auto-show-system-loading="true"> 9 <z-paging ref="pagingRef" v-model="currentList" @query="fetchData" :auto-show-system-loading="true">
@@ -12,43 +12,61 @@ @@ -12,43 +12,61 @@
12 </template> 12 </template>
13 <view class="card-list"> 13 <view class="card-list">
14 <view class="task-card" v-for="(item, index) in currentList" :key="`${item.planNo}_${index}`"> 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 <view class="plan-name u-line-1">{{ item.planName || '无计划名称' }}</view> 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 </view> 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 </view> 25 </view>
34 - <!-- 第三行:有效期 + 结束任务按钮 -->  
35 - <view class="row row-3"> 26 + <!-- 有效期 -->
  27 + <view class="info-row">
36 <!-- timeFormat(start, 'yyyy-mm-dd'), --> 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 timeFormat(item.endTime, 'yyyy-mm-dd') }} 31 timeFormat(item.endTime, 'yyyy-mm-dd') }}
39 </view> 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 </view> 50 </view>
44 </view> 51 </view>
45 </view> 52 </view>
46 </z-paging> 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 :showCancelButton="true" @cancel="handleInvalidModalCancel" @confirm="confirmSetInvalid"> 56 :showCancelButton="true" @cancel="handleInvalidModalCancel" @confirm="confirmSetInvalid">
50 <view class="invalid-modal-content"> 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 </view> 70 </view>
53 </up-modal> 71 </up-modal>
54 <!-- ========== 结束任务二次确认弹窗 ========== --> 72 <!-- ========== 结束任务二次确认弹窗 ========== -->
@@ -61,10 +79,10 @@ @@ -61,10 +79,10 @@
61 </view> 79 </view>
62 </template> 80 </template>
63 <script setup lang="ts"> 81 <script setup lang="ts">
64 -import { ref, computed } from 'vue' 82 +import { ref } from 'vue'
65 import { onShow, onUnload, onLoad } from '@dcloudio/uni-app' 83 import { onShow, onUnload, onLoad } from '@dcloudio/uni-app'
66 -import { useUserStore } from '@/pinia/user';  
67 import { maintainPlanNum, finishPlan, invalidatePlan, maintainCreate } from "@/api/maintain-manage/maintain-manage"; 84 import { maintainPlanNum, finishPlan, invalidatePlan, maintainCreate } from "@/api/maintain-manage/maintain-manage";
  85 +import { uploadImages } from '@/common/utils/upload';
68 import { timeFormat } from '@/uni_modules/uview-plus'; 86 import { timeFormat } from '@/uni_modules/uview-plus';
69 /** 获取当天日期 yyyy-MM-dd */ 87 /** 获取当天日期 yyyy-MM-dd */
70 const getTodayStr = () => { 88 const getTodayStr = () => {
@@ -74,14 +92,9 @@ const getTodayStr = () =&gt; { @@ -74,14 +92,9 @@ const getTodayStr = () =&gt; {
74 const day = String(d.getDate()).padStart(2, '0') 92 const day = String(d.getDate()).padStart(2, '0')
75 return `${year}-${month}-${day}` 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 const statusTabs = ref([ 98 const statusTabs = ref([
86 { name: '待完成', id: '1' }, 99 { name: '待完成', id: '1' },
87 { name: '已失效', id: '3' }, 100 { name: '已失效', id: '3' },
@@ -97,6 +110,10 @@ const allTotalData = ref&lt;any[]&gt;([]) @@ -97,6 +110,10 @@ const allTotalData = ref&lt;any[]&gt;([])
97 // ===================== 失效弹窗状态 ===================== 110 // ===================== 失效弹窗状态 =====================
98 const invalidModalShow = ref(false) 111 const invalidModalShow = ref(false)
99 const currentInvalidItem = ref(null) 112 const currentInvalidItem = ref(null)
  113 +// 失效原因(必填,提交时作为 invalidReason 传给后端)
  114 +const invalidReason = ref('')
  115 +// 失效凭证(选填,最多 3 张,上传成功后取 url 作为 invalidFiles)
  116 +const invalidImages = ref<any[]>([])
100 // ===================== 结束任务确认弹窗 ===================== 117 // ===================== 结束任务确认弹窗 =====================
101 const endTaskModalShow = ref(false) 118 const endTaskModalShow = ref(false)
102 const currentEndTaskItem = ref<any>(null) 119 const currentEndTaskItem = ref<any>(null)
@@ -104,6 +121,9 @@ const currentEndTaskItem = ref&lt;any&gt;(null) @@ -104,6 +121,9 @@ const currentEndTaskItem = ref&lt;any&gt;(null)
104 const loadData = async () => { 121 const loadData = async () => {
105 console.log('123123') 122 console.log('123123')
106 if (!originRawList || originRawList.length === 0) { 123 if (!originRawList || originRawList.length === 0) {
  124 + // 没有批次时要显式结束分页,否则 z-paging 收不到 complete,页面一直停在加载中
  125 + allTotalData.value = []
  126 + pagingRef.value?.complete([], 0)
107 return 127 return
108 } 128 }
109 uni.showLoading({ title: '加载数据...', mask: true }) 129 uni.showLoading({ title: '加载数据...', mask: true })
@@ -179,12 +199,60 @@ const handleStatusChange = async (tabItem) =&gt; { @@ -179,12 +199,60 @@ const handleStatusChange = async (tabItem) =&gt; {
179 // 打开失效弹窗 199 // 打开失效弹窗
180 const handleSetInvalid = (item) => { 200 const handleSetInvalid = (item) => {
181 currentInvalidItem.value = item 201 currentInvalidItem.value = item
  202 + invalidReason.value = ''
  203 + invalidImages.value = []
182 invalidModalShow.value = true 204 invalidModalShow.value = true
183 } 205 }
184 // 关闭弹窗,重置数据 206 // 关闭弹窗,重置数据
185 const handleInvalidModalCancel = () => { 207 const handleInvalidModalCancel = () => {
186 invalidModalShow.value = false 208 invalidModalShow.value = false
187 currentInvalidItem.value = null 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 const confirmSetInvalid = async () => { 258 const confirmSetInvalid = async () => {
@@ -194,6 +262,20 @@ const confirmSetInvalid = async () =&gt; { @@ -194,6 +262,20 @@ const confirmSetInvalid = async () =&gt; {
194 uni.showToast({ title: '数据异常', icon: 'none', duration:2000 }) 262 uni.showToast({ title: '数据异常', icon: 'none', duration:2000 })
195 return 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 uni.showLoading({ title: '提交中...', mask: true }) 279 uni.showLoading({ title: '提交中...', mask: true })
198 try { 280 try {
199 let targetCommitId = item.commitId 281 let targetCommitId = item.commitId
@@ -217,8 +299,10 @@ const confirmSetInvalid = async () =&gt; { @@ -217,8 +299,10 @@ const confirmSetInvalid = async () =&gt; {
217 } 299 }
218 const params = { 300 const params = {
219 commitId: targetCommitId, 301 commitId: targetCommitId,
220 - invalidReason: '管理员手动置为失效',  
221 - invalidFiles: '' 302 + // 使用弹窗中填写的原因(必填),不再写死默认文案
  303 + invalidReason: reason,
  304 + // 后端 invalidFiles 是 List<String>,无图时传空数组
  305 + invalidFiles
222 } 306 }
223 console.log('置为失效提交参数:', params) 307 console.log('置为失效提交参数:', params)
224 await invalidatePlan(params) 308 await invalidatePlan(params)
@@ -265,23 +349,13 @@ const confirmEndTask = async () =&gt; { @@ -265,23 +349,13 @@ const confirmEndTask = async () =&gt; {
265 endTaskModalShow.value = false 349 endTaskModalShow.value = false
266 uni.showLoading({ title: '提交中...', mask: true }) 350 uni.showLoading({ title: '提交中...', mask: true })
267 try { 351 try {
268 - let targetCommitId = item.commitId  
269 - // 不存在commitId,先创建草稿 352 + const targetCommitId = item.commitId
  353 + // 没有进行中的上报说明本次还没作业:后端结束任务要求至少一条正常作业记录,
  354 + // 先建草稿再结束必定失败,还会留下一条永远「进行中」的脏草稿,这里直接拦下。
270 if (!targetCommitId) { 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 await finishPlan({ commitId: targetCommitId }) 360 await finishPlan({ commitId: targetCommitId })
287 uni.hideLoading() 361 uni.hideLoading()
@@ -305,61 +379,122 @@ onUnload(() =&gt; { @@ -305,61 +379,122 @@ onUnload(() =&gt; {
305 <style scoped lang="scss"> 379 <style scoped lang="scss">
306 .page-container { 380 .page-container {
307 height: 100vh; 381 height: 100vh;
308 - background-color: #f5f5f5; 382 + background-color: #F4F6FA;
309 } 383 }
310 .sticky-wrap { 384 .sticky-wrap {
311 background: #fff; 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 .card-list { 391 .card-list {
315 - padding: 100rpx 20rpx 20rpx; 392 + padding: 112rpx 24rpx 24rpx;
316 display: flex; 393 display: flex;
317 flex-direction: column; 394 flex-direction: column;
318 - gap: 20rpx; 395 + gap: 24rpx;
319 } 396 }
  397 +/* 卡片:12px 内边距 / 8px 圆角 / 卡片阴影(设计稿 .tcard) */
320 .task-card { 398 .task-card {
321 background: #fff; 399 background: #fff;
322 - border-radius: 12rpx; 400 + border-radius: 16rpx;
323 padding: 24rpx; 401 padding: 24rpx;
  402 + box-shadow: 0 4rpx 16rpx rgba(17, 24, 39, 0.06);
324 display: flex; 403 display: flex;
325 flex-direction: column; 404 flex-direction: column;
326 - gap: 20rpx;  
327 } 405 }
328 -.row { 406 +/* 标题行:标题占满剩余宽度,状态标签靠右(设计稿 .tcard-head) */
  407 +.card-head {
329 display: flex; 408 display: flex;
330 align-items: center; 409 align-items: center;
331 - justify-content: space-between;  
332 gap: 16rpx; 410 gap: 16rpx;
  411 + margin-bottom: 16rpx;
333 } 412 }
334 .plan-name { 413 .plan-name {
335 - font-size: 30rpx;  
336 - color: #333;  
337 - font-weight: 500;  
338 flex: 1; 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 font-size: 26rpx; 429 font-size: 26rpx;
342 - color: #1677ff; 430 + color: #9CA3AF;
343 flex-shrink: 0; 431 flex-shrink: 0;
344 - padding-left: 16rpx;  
345 } 432 }
346 -.info-text {  
347 - font-size: 26rpx;  
348 - color: #666; 433 +.info-value {
349 flex: 1; 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 .invalid-modal-content { 476 .invalid-modal-content {
361 width: 100%; 477 width: 100%;
362 box-sizing: border-box; 478 box-sizing: border-box;
363 padding: 10rpx 0; 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 </style> 500 </style>
pages-sub/daily/maintain-manage/type-list.vue
1 <template> 1 <template>
2 - <view class="tag-wrap">  
3 - <!-- 动态渲染标签列表 --> 2 + <view class="type-grid">
  3 + <!-- 动态渲染养护类型卡片 -->
4 <template v-if="tagList.length > 0"> 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 @click="toNextPage(item)"> 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 </view> 13 </view>
12 </view> 14 </view>
13 </template> 15 </template>
14 <template v-else> 16 <template v-else>
15 - <view style="padding-top: 30px;text-align: center;width: 100%;">暂无养护类型,请去平台配置</view> 17 + <view class="type-empty">暂无养护类型,请去平台配置</view>
16 </template> 18 </template>
17 </view> 19 </view>
18 </template> 20 </template>
@@ -55,42 +57,94 @@ onUnload(()=&gt;{ @@ -55,42 +57,94 @@ onUnload(()=&gt;{
55 }) 57 })
56 </script> 58 </script>
57 <style scoped lang="scss"> 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 &--hover { 80 &--hover {
74 - background: #d8eaff; 81 + background: #F4F5F7;
75 } 82 }
76 } 83 }
77 -.tag-text { 84 +
  85 +/* 类型图标位:68rpx 方块 + 淡蓝底(设计稿 .type-ico) */
  86 +.type-icon {
78 display: flex; 87 display: flex;
79 align-items: center; 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 white-space: nowrap; 106 white-space: nowrap;
85 overflow: hidden; 107 overflow: hidden;
86 text-overflow: ellipsis; 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 flex-shrink: 0; 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 </style> 150 </style>
pages-sub/daily/patrol-manage/add-patrol-record.vue
1 <template> 1 <template>
2 <view class="u-page"> 2 <view class="u-page">
3 <!-- 原有模板内容不变,仅调整表单校验相关配置 --> 3 <!-- 原有模板内容不变,仅调整表单校验相关配置 -->
4 - <view class="inspect-form-content commonPageLRpadding"> 4 + <view class="inspect-form-content">
5 <up-form label-position="left" :model="inspectForm" ref="inspectFormRef" labelWidth="200rpx"> 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 </up-form> 88 </up-form>
65 </view> 89 </view>
66 <!-- 底部提交按钮 --> 90 <!-- 底部提交按钮 -->
67 <view class="fixed-bottom-btn-wrap"> 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 </view> 93 </view>
71 <!-- 紧急程度下拉弹窗 --> 94 <!-- 紧急程度下拉弹窗 -->
72 <up-action-sheet :show="showActionSheet" :actions="pressingTypeList" title="请选择紧急程度" @close="handleActionSheetClose" 95 <up-action-sheet :show="showActionSheet" :actions="pressingTypeList" title="请选择紧急程度" @close="handleActionSheetClose"
@@ -470,14 +493,114 @@ export default { @@ -470,14 +493,114 @@ export default {
470 <style lang="scss" scoped> 493 <style lang="scss" scoped>
471 .u-page { 494 .u-page {
472 min-height: 100vh; 495 min-height: 100vh;
  496 + padding-bottom: 200rpx;
  497 + background-color: #F4F6FA;
  498 + box-sizing: border-box;
473 } 499 }
474 500
475 .inspect-form-content { 501 .inspect-form-content {
476 - background: #fff;  
477 - padding: 20rpx; 502 + padding: 0 24rpx;
  503 + background: transparent;
478 } 504 }
479 505
480 .form-item { 506 .form-item {
481 margin-bottom: 20rpx; 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 </style> 606 </style>
pages-sub/daily/patrol-manage/finish-plan-detail.vue
@@ -5,93 +5,61 @@ @@ -5,93 +5,61 @@
5 v-if="loading" 5 v-if="loading"
6 :loading="true" 6 :loading="true"
7 title="加载中..." 7 title="加载中..."
8 - color="#3c9cff" 8 + color="#2563EB"
9 ></up-loading-page> 9 ></up-loading-page>
10 10
11 <!-- 内容容器 --> 11 <!-- 内容容器 -->
12 <template v-else> 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 </view> 63 </view>
96 </view> 64 </view>
97 <view v-else> 65 <view v-else>
@@ -145,14 +113,58 @@ onLoad((options) =&gt; { @@ -145,14 +113,58 @@ onLoad((options) =&gt; {
145 </script> 113 </script>
146 114
147 <style scoped lang="scss"> 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 box-sizing: border-box; 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 </style> 170 </style>
159 \ No newline at end of file 171 \ No newline at end of file
pages-sub/daily/patrol-manage/index.vue
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 :list="tabList" 7 :list="tabList"
8 :is-scroll="false" 8 :is-scroll="false"
9 :activeStyle="{ 9 :activeStyle="{
10 - color: '#3c9cff', 10 + color: '#2563EB',
11 fontWeight: 'bold', 11 fontWeight: 'bold',
12 transform: 'scale(1.05)' 12 transform: 'scale(1.05)'
13 }" 13 }"
@@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
29 @custom="handleSearch" 29 @custom="handleSearch"
30 :clearabled="false" 30 :clearabled="false"
31 maxlength="50" 31 maxlength="50"
32 - style="margin: 20rpx 20rpx 0" 32 + style="margin: 16rpx 24rpx 0"
33 ></up-search> 33 ></up-search>
34 </view> 34 </view>
35 </up-sticky> 35 </up-sticky>
@@ -44,53 +44,51 @@ @@ -44,53 +44,51 @@
44 <empty-view/> 44 <empty-view/>
45 </template> 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 </view> 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 </view> 92 </view>
95 93
96 </z-paging> 94 </z-paging>
@@ -182,9 +180,39 @@ onShow(() =&gt; { @@ -182,9 +180,39 @@ onShow(() =&gt; {
182 } 180 }
183 .sticky-header { 181 .sticky-header {
184 background-color: #ffffff; 182 background-color: #ffffff;
185 - padding-bottom: 10rpx; 183 + padding-bottom: 24rpx;
  184 + border-bottom: 1rpx solid #E8EBF0;
186 .search-input { 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 </style> 218 </style>
191 \ No newline at end of file 219 \ No newline at end of file
pages-sub/daily/patrol-manage/pending-plan-detail.vue
1 <template> 1 <template>
2 <view class="page-container"> 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 </view> 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 </view> 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 </view> 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 </view> 59 </view>
105 60
106 61
@@ -110,7 +65,6 @@ @@ -110,7 +65,6 @@
110 type="primary" 65 type="primary"
111 size="default" 66 size="default"
112 @click="addNewRecord" 67 @click="addNewRecord"
113 - :style="{ width: '100%', height: '88rpx', fontSize: '32rpx', borderRadius: 0 }"  
114 > 68 >
115 新增记录 69 新增记录
116 </up-button> 70 </up-button>
@@ -171,6 +125,90 @@ const addNewRecord = () =&gt; { @@ -171,6 +125,90 @@ const addNewRecord = () =&gt; {
171 </script> 125 </script>
172 126
173 <style scoped lang="scss"> 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 </style> 214 </style>
177 \ No newline at end of file 215 \ No newline at end of file
pages-sub/daily/quick-order/add-order.vue
1 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 <!-- 核心:将所有 up-form-item 包裹在同一个 up-form 内 --> 3 <!-- 核心:将所有 up-form-item 包裹在同一个 up-form 内 -->
4 - <view class="work-order-form-content commonPageLRpadding"> 4 + <view class="work-order-form-content">
5 <up-form 5 <up-form
6 label-position="left" 6 label-position="left"
7 :model="workOrderForm" 7 :model="workOrderForm"
8 ref="workOrderFormRef" 8 ref="workOrderFormRef"
9 labelWidth="160rpx" 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 <!-- 4. 情况描述(文本域) --> 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 </up-form> 184 </up-form>
147 </view> 185 </view>
@@ -150,7 +188,7 @@ @@ -150,7 +188,7 @@
150 <up-button 188 <up-button
151 type="primary" 189 type="primary"
152 size="large" 190 size="large"
153 - text="提交工单" 191 + text="提交"
154 @click="submitWorkOrder" 192 @click="submitWorkOrder"
155 ></up-button> 193 ></up-button>
156 </view> 194 </view>
@@ -585,14 +623,118 @@ export default { @@ -585,14 +623,118 @@ export default {
585 </script> 623 </script>
586 624
587 <style lang="scss" scoped> 625 <style lang="scss" scoped>
588 -// 全局页面样式 626 +/* 统一卡片样式(与工单/巡查表单页一致) */
589 .page-container { 627 .page-container {
590 min-height: 100vh; 628 min-height: 100vh;
  629 + padding-bottom: 200rpx;
  630 + background-color: #F4F6FA;
  631 + box-sizing: border-box;
591 } 632 }
592 633
593 // 工单表单内容容器 634 // 工单表单内容容器
594 .work-order-form-content { 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 </style> 740 </style>
599 \ No newline at end of file 741 \ No newline at end of file
pages-sub/daily/quick-order/index.vue
@@ -43,64 +43,37 @@ @@ -43,64 +43,37 @@
43 <empty-view/> 43 <empty-view/>
44 </template> 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 </view> 77 </view>
105 </z-paging> 78 </z-paging>
106 79
@@ -174,11 +147,34 @@ const handleAddOrder = () =&gt; { @@ -174,11 +147,34 @@ const handleAddOrder = () =&gt; {
174 </script> 147 </script>
175 148
176 <style scoped lang="scss"> 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 .search-header { 174 .search-header {
179 display: flex; 175 display: flex;
180 align-items: center; 176 align-items: center;
181 - padding: 20rpx; 177 + padding: 24rpx;
182 background-color: #fff; 178 background-color: #fff;
183 box-sizing: border-box; 179 box-sizing: border-box;
184 180
pages-sub/daily/quick-order/order-detail.vue
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 v-if="loading" 5 v-if="loading"
6 :loading="true" 6 :loading="true"
7 title="加载中..." 7 title="加载中..."
8 - color="#3c9cff" 8 + color="#2563EB"
9 ></up-loading-page> 9 ></up-loading-page>
10 10
11 <!-- 内容容器 --> 11 <!-- 内容容器 -->
@@ -16,109 +16,87 @@ @@ -16,109 +16,87 @@
16 </view> 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 <up-album 66 <up-album
81 - :urls="orderDetail.problemsImgs " 67 + :urls="orderDetail.problemsImgs"
82 singleSize="70" 68 singleSize="70"
83 multipleSize="70" 69 multipleSize="70"
84 :preview-full-image="true" 70 :preview-full-image="true"
85 -  
86 ></up-album> 71 ></up-album>
87 -<!-- <text v-else class="empty-text">暂无问题照片</text>-->  
88 </view> 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 <view class="cell-content-wrap"> 81 <view class="cell-content-wrap">
96 <up-album 82 <up-album
97 -  
98 :urls="orderDetail.endImgs" 83 :urls="orderDetail.endImgs"
99 singleSize="70" 84 singleSize="70"
100 multipleSize="70" 85 multipleSize="70"
101 :preview-full-image="true" 86 :preview-full-image="true"
102 -  
103 ></up-album> 87 ></up-album>
104 -<!-- <text v-else class="empty-text">暂无完成照片</text>-->  
105 </view> 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 </view> 100 </view>
123 </view> 101 </view>
124 </template> 102 </template>
@@ -176,20 +154,85 @@ onLoad((options) =&gt; { @@ -176,20 +154,85 @@ onLoad((options) =&gt; {
176 </script> 154 </script>
177 155
178 <style scoped lang="scss"> 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 .content-wrap { 166 .content-wrap {
182 - background: #fff;  
183 width: 100%; 167 width: 100%;
184 box-sizing: border-box; 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 .cell-content-wrap { 231 .cell-content-wrap {
  232 + padding-top: 12rpx;
188 :deep(image) { // 小程序中图片标签是image,且需要穿透样式隔离 233 :deep(image) { // 小程序中图片标签是image,且需要穿透样式隔离
189 width: 70px !important; 234 width: 70px !important;
190 height: 70px !important; 235 height: 70px !important;
191 } 236 }
192 } 237 }
193 -  
194 -  
195 </style> 238 </style>
196 \ No newline at end of file 239 \ No newline at end of file
pages-sub/data/tree-archive/addInspect.vue
@@ -295,7 +295,7 @@ @@ -295,7 +295,7 @@
295 <!-- 栽种年月:标题下方、单选上方,绑定表单字段 inspectForm.weight.plantingDate --> 295 <!-- 栽种年月:标题下方、单选上方,绑定表单字段 inspectForm.weight.plantingDate -->
296 <view class="date-select-row" @click="showDatePicker = true" :class="pageType === 'detail' ? 'disabled-row' : ''"> 296 <view class="date-select-row" @click="showDatePicker = true" :class="pageType === 'detail' ? 'disabled-row' : ''">
297 <text>{{ inspectForm.weight.plantingDate || '请选择栽种年月' }}</text> 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 </view> 299 </view>
300 300
301 <u-radio-group 301 <u-radio-group
@@ -401,7 +401,7 @@ @@ -401,7 +401,7 @@
401 </u-collapse> 401 </u-collapse>
402 402
403 <view class="risk-result-wrap"> 403 <view class="risk-result-wrap">
404 - <view style="padding-bottom: 10px;">风险评估结果</view> 404 + <view class="risk-result-title">风险评估结果</view>
405 <view class="risk-item"> 405 <view class="risk-item">
406 <text class="risk-label">常规安全风险得分:</text> 406 <text class="risk-label">常规安全风险得分:</text>
407 <text class="risk-value">{{ riskResult.normalScore }}</text> 407 <text class="risk-value">{{ riskResult.normalScore }}</text>
@@ -1045,58 +1045,106 @@ onUnload(() =&gt; { @@ -1045,58 +1045,106 @@ onUnload(() =&gt; {
1045 <style scoped lang="scss"> 1045 <style scoped lang="scss">
1046 .inspect-add-container { 1046 .inspect-add-container {
1047 min-height: 100vh; 1047 min-height: 100vh;
1048 - background-color: #fff; 1048 + padding: 0 24rpx;
  1049 + box-sizing: border-box;
  1050 + background-color: #F4F6FA;
1049 } 1051 }
1050 .inspect-scroll { 1052 .inspect-scroll {
1051 height: calc(100vh - 120rpx); 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 .question-wrap { 1090 .question-wrap {
1054 padding: 15rpx 0; 1091 padding: 15rpx 0;
1055 - border-bottom: 1rpx solid #f0f0f0; 1092 + border-bottom: 1rpx solid #E8EBF0;
1056 &:last-child { 1093 &:last-child {
1057 border-bottom: none; 1094 border-bottom: none;
1058 } 1095 }
1059 } 1096 }
1060 .question-title { 1097 .question-title {
1061 - font-size: 14px; 1098 + font-size: 28rpx;
1062 line-height: 1.5; 1099 line-height: 1.5;
1063 margin: 15rpx 0; 1100 margin: 15rpx 0;
1064 - color: #333; 1101 + color: #1F2937;
1065 .required { 1102 .required {
1066 - color: #ff0000; 1103 + color: #DC2626;
1067 margin-right: 5rpx; 1104 margin-right: 5rpx;
1068 } 1105 }
1069 } 1106 }
  1107 +/* 风险评估结果:独立白色卡片(设计稿 .card) */
1070 .risk-result-wrap { 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 .risk-item { 1121 .risk-item {
1074 display: flex; 1122 display: flex;
1075 align-items: center; 1123 align-items: center;
1076 margin-bottom: 15rpx; 1124 margin-bottom: 15rpx;
1077 - font-size: 14px; 1125 + font-size: 26rpx;
1078 .risk-label { 1126 .risk-label {
1079 - color: #666; 1127 + color: #9CA3AF;
1080 margin-right: 10rpx; 1128 margin-right: 10rpx;
1081 } 1129 }
1082 .risk-value { 1130 .risk-value {
1083 - color: #333; 1131 + color: #1F2937;
1084 font-weight: 500; 1132 font-weight: 500;
1085 } 1133 }
1086 } 1134 }
1087 .emergency-wrap {} 1135 .emergency-wrap {}
1088 1136
1089 .risk-level-low { 1137 .risk-level-low {
1090 - color: #00b42a; 1138 + color: #16A34A;
1091 } 1139 }
1092 .risk-level-normal { 1140 .risk-level-normal {
1093 - color: #1989fa; 1141 + color: #2563EB;
1094 } 1142 }
1095 .risk-level-warning { 1143 .risk-level-warning {
1096 - color: #ff9500; 1144 + color: #D97706;
1097 } 1145 }
1098 .risk-level-danger { 1146 .risk-level-danger {
1099 - color: #ff0000; 1147 + color: #DC2626;
1100 } 1148 }
1101 1149
1102 // 只读状态置灰 1150 // 只读状态置灰
@@ -1109,9 +1157,9 @@ onUnload(() =&gt; { @@ -1109,9 +1157,9 @@ onUnload(() =&gt; {
1109 .modal-risk-content { 1157 .modal-risk-content {
1110 padding: 10px 0; 1158 padding: 10px 0;
1111 .modal-row { 1159 .modal-row {
1112 - font-size: 14px; 1160 + font-size: 26rpx;
1113 line-height: 2; 1161 line-height: 2;
1114 - color: #333; 1162 + color: #4B5563;
1115 } 1163 }
1116 } 1164 }
1117 1165
@@ -1126,6 +1174,8 @@ onUnload(() =&gt; { @@ -1126,6 +1174,8 @@ onUnload(() =&gt; {
1126 :deep(.u-radio__text) { 1174 :deep(.u-radio__text) {
1127 min-width: 220rpx; /* 根据需求自行调大/调小 */ 1175 min-width: 220rpx; /* 根据需求自行调大/调小 */
1128 display: inline-block; 1176 display: inline-block;
  1177 + font-size: 26rpx;
  1178 + color: #4B5563;
1129 } 1179 }
1130 1180
1131 /* 单列单选组,增加上下间距,避免误触 */ 1181 /* 单列单选组,增加上下间距,避免误触 */
@@ -1137,15 +1187,16 @@ onUnload(() =&gt; { @@ -1137,15 +1187,16 @@ onUnload(() =&gt; {
1137 display: flex; 1187 display: flex;
1138 justify-content: space-between; 1188 justify-content: space-between;
1139 align-items: center; 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 margin-bottom: 12rpx; 1196 margin-bottom: 12rpx;
1146 &.disabled-row { 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 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 <up-form :model="formData" ref="formRef" label-width="140rpx" border-bottom> 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 </up-form-item> 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 <view class="form-row-wrap"> 26 <view class="form-row-wrap">
111 <up-row gutter="10"> 27 <up-row gutter="10">
112 <up-col span="6"> 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 </up-form-item> 34 </up-form-item>
117 </up-col> 35 </up-col>
118 <up-col span="6"> 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 input-align="left"/> 39 input-align="left"/>
122 <template #right> 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 </template> 42 </template>
125 </up-form-item> 43 </up-form-item>
126 </up-col> 44 </up-col>
127 </up-row> 45 </up-row>
128 </view> 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 <up-row gutter="10"> 125 <up-row gutter="10">
132 <up-col span="6"> 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 </up-form-item> 129 </up-form-item>
140 </up-col> 130 </up-col>
141 <up-col span="6"> 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 <template #right> 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 </template> 137 </template>
148 </up-form-item> 138 </up-form-item>
149 </up-col> 139 </up-col>
150 </up-row> 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 </view> 189 </view>
152 </view> 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 </up-form> 197 </up-form>
164 198
165 <view style="height: 60px;width: 100%"></view> 199 <view style="height: 60px;width: 100%"></view>
@@ -513,10 +547,172 @@ const submit = async () =&gt; { @@ -513,10 +547,172 @@ const submit = async () =&gt; {
513 </script> 547 </script>
514 548
515 <style scoped lang="scss"> 549 <style scoped lang="scss">
  550 +/* 页面底色 + 留白(设计稿 --page-bg / .body) */
516 .page-container { 551 .page-container {
517 - padding: 15px; 552 + padding: 24rpx;
  553 + padding-bottom: 200rpx; // 给底部固定按钮留空间
518 box-sizing: border-box; 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 .animated-area { 718 .animated-area {
@@ -541,7 +737,7 @@ const submit = async () =&gt; { @@ -541,7 +737,7 @@ const submit = async () =&gt; {
541 left: 0; 737 left: 0;
542 bottom: -20rpx; 738 bottom: -20rpx;
543 line-height: 20rpx; 739 line-height: 20rpx;
544 - font-size: 22rpx; 740 + font-size: 24rpx;
545 color: #f56c6c; 741 color: #f56c6c;
546 width: 100%; 742 width: 100%;
547 box-sizing: border-box; 743 box-sizing: border-box;
pages-sub/data/tree-archive/editTree.vue
@@ -6,8 +6,8 @@ @@ -6,8 +6,8 @@
6 <up-tabs 6 <up-tabs
7 v-model="activeTab" 7 v-model="activeTab"
8 :list="tabList" 8 :list="tabList"
9 - active-color="#1989fa"  
10 - inactive-color="#666" 9 + active-color="#2563EB"
  10 + inactive-color="#606266"
11 font-size="30rpx" 11 font-size="30rpx"
12 @click="handleTabChange" 12 @click="handleTabChange"
13 :scrollable="false" 13 :scrollable="false"
@@ -17,6 +17,11 @@ @@ -17,6 +17,11 @@
17 17
18 <!-- Tab0 基本信息页面 --> 18 <!-- Tab0 基本信息页面 -->
19 <view v-show="activeTab === 0" class="base-info-wrap"> 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 <up-form :model="formData" ref="formRef" label-width="140rpx" border-bottom> 25 <up-form :model="formData" ref="formRef" label-width="140rpx" border-bottom>
21 <up-form-item label="名称" prop="treetype" required> 26 <up-form-item label="名称" prop="treetype" required>
22 <up-input v-model.trim="formData.treetype" placeholder="请输入名称" maxlength="30" border="none"/> 27 <up-input v-model.trim="formData.treetype" placeholder="请输入名称" maxlength="30" border="none"/>
@@ -40,7 +45,7 @@ @@ -40,7 +45,7 @@
40 <up-input v-model.trim="formData.dbh" placeholder="请输入" maxlength="10" border="none" 45 <up-input v-model.trim="formData.dbh" placeholder="请输入" maxlength="10" border="none"
41 input-align="left"/> 46 input-align="left"/>
42 <template #right> 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 </template> 49 </template>
45 </up-form-item> 50 </up-form-item>
46 </up-col> 51 </up-col>
@@ -49,7 +54,7 @@ @@ -49,7 +54,7 @@
49 <up-input v-model.trim="formData.treeheight" placeholder="请输入" maxlength="10" border="none" 54 <up-input v-model.trim="formData.treeheight" placeholder="请输入" maxlength="10" border="none"
50 input-align="left"/> 55 input-align="left"/>
51 <template #right> 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 </template> 58 </template>
54 </up-form-item> 59 </up-form-item>
55 </up-col> 60 </up-col>
@@ -140,7 +145,7 @@ @@ -140,7 +145,7 @@
140 <up-input v-model.trim="formData.weekday" placeholder="请输入" maxlength="10" border="none" 145 <up-input v-model.trim="formData.weekday" placeholder="请输入" maxlength="10" border="none"
141 input-align="left"/> 146 input-align="left"/>
142 <template #right> 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 </template> 149 </template>
145 </up-form-item> 150 </up-form-item>
146 </up-col> 151 </up-col>
@@ -154,7 +159,7 @@ @@ -154,7 +159,7 @@
154 <up-input v-model.trim="formData.canopyeastwest" placeholder="请输入" maxlength="10" border="none" 159 <up-input v-model.trim="formData.canopyeastwest" placeholder="请输入" maxlength="10" border="none"
155 input-align="left"/> 160 input-align="left"/>
156 <template #right> 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 </template> 163 </template>
159 </up-form-item> 164 </up-form-item>
160 </up-col> 165 </up-col>
@@ -163,7 +168,7 @@ @@ -163,7 +168,7 @@
163 <up-input v-model.trim="formData.canopysouthnorth" placeholder="请输入" maxlength="10" border="none" 168 <up-input v-model.trim="formData.canopysouthnorth" placeholder="请输入" maxlength="10" border="none"
164 input-align="left"/> 169 input-align="left"/>
165 <template #right> 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 </template> 172 </template>
168 </up-form-item> 173 </up-form-item>
169 </up-col> 174 </up-col>
@@ -232,11 +237,11 @@ @@ -232,11 +237,11 @@
232 <view style="text-align: right">{{ timeFormat(item.updatetime) }}</view> 237 <view style="text-align: right">{{ timeFormat(item.updatetime) }}</view>
233 </view> 238 </view>
234 <view class=" fs-align__center" style="margin: 8px 0"> 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 alt=""> 高度:{{ item.treeheight }} 米 241 alt=""> 高度:{{ item.treeheight }} 米
237 </view> 242 </view>
238 <view class=" fs-align__center"> 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 alt="">胸径:{{ item.dbh }} 厘米 245 alt="">胸径:{{ item.dbh }} 厘米
241 </view> 246 </view>
242 </view> 247 </view>
@@ -700,18 +705,68 @@ const toAddInspect = () =&gt; { @@ -700,18 +705,68 @@ const toAddInspect = () =&gt; {
700 <style scoped lang="scss"> 705 <style scoped lang="scss">
701 .container { 706 .container {
702 min-height: 100vh; 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 .header-wrap { 713 .header-wrap {
707 - background-color: #fff; 714 + background-color: #ffffff;
708 padding: 10rpx 0; 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 .base-info-wrap { 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 .log-wrap, .inspect-wrap { 772 .log-wrap, .inspect-wrap {
@@ -719,39 +774,65 @@ const toAddInspect = () =&gt; { @@ -719,39 +774,65 @@ const toAddInspect = () =&gt; {
719 } 774 }
720 775
721 .record-wrap { 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 .treetypeName { 791 .treetypeName {
726 flex: 1; 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 .record-list-left { 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 background-repeat: no-repeat; 805 background-repeat: no-repeat;
736 background-position: center; 806 background-position: center;
  807 + flex-shrink: 0;
737 } 808 }
738 809
739 .record-list-right { 810 .record-list-right {
740 - margin-left: 20px; 811 + margin-left: 24rpx;
741 flex: 1; 812 flex: 1;
  813 + min-width: 0;
742 overflow: hidden; 814 overflow: hidden;
743 } 815 }
744 816
  817 +/* 树木编号:浅绿标签(设计稿 .tag.done) */
745 .treenumber-no { 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 .card-body-inner { 832 .card-body-inner {
753 display: flex; 833 display: flex;
754 - font-size: 12px; 834 + font-size: 26rpx;
  835 + color: #4B5563;
755 } 836 }
756 837
757 .fs-align__center { 838 .fs-align__center {
@@ -783,7 +864,7 @@ const toAddInspect = () =&gt; { @@ -783,7 +864,7 @@ const toAddInspect = () =&gt; {
783 left: 0; 864 left: 0;
784 bottom: -20rpx; 865 bottom: -20rpx;
785 line-height: 20rpx; 866 line-height: 20rpx;
786 - font-size: 22rpx; 867 + font-size: 24rpx;
787 color: #f56c6c; 868 color: #f56c6c;
788 width: 100%; 869 width: 100%;
789 box-sizing: border-box; 870 box-sizing: border-box;
@@ -807,11 +888,12 @@ const toAddInspect = () =&gt; { @@ -807,11 +888,12 @@ const toAddInspect = () =&gt; {
807 888
808 /* 巡检记录样式 */ 889 /* 巡检记录样式 */
809 .inspect-row { 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 .detail-text { 895 .detail-text {
814 - color: #1989fa;  
815 - font-size: 14px; 896 + color: #2563EB;
  897 + font-size: 24rpx;
816 } 898 }
817 </style> 899 </style>
818 \ No newline at end of file 900 \ No newline at end of file
pages-sub/data/tree-archive/index.vue
1 <template> 1 <template>
2 <view class="container"> 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 </view> 21 </view>
39 22
40 <!-- ✅ 核心:uview-plus up-row+up-col 实现左右布局【无u-scroll-list,无任何多余组件】 --> 23 <!-- ✅ 核心:uview-plus up-row+up-col 实现左右布局【无u-scroll-list,无任何多余组件】 -->
41 <up-row type="flex" class="cate-layout" align="flex-start"> 24 <up-row type="flex" class="cate-layout" align="flex-start">
42 <!-- 左侧:班组列表 (uview栅格列 + 原生滚动) --> 25 <!-- 左侧:班组列表 (uview栅格列 + 原生滚动) -->
43 <up-col span="3" class="cate-left"> 26 <up-col span="3" class="cate-left">
  27 + <!-- 补滚动容器:班组数量多时可滚动(.left-scroll 样式原本已定义但未挂载) -->
  28 + <scroll-view scroll-y class="left-scroll">
44 <view 29 <view
45 class="left-item" 30 class="left-item"
46 :class="{ active: currentIndex === index }" 31 :class="{ active: currentIndex === index }"
@@ -50,7 +35,7 @@ @@ -50,7 +35,7 @@
50 > 35 >
51 {{ item.deptName }} 36 {{ item.deptName }}
52 </view> 37 </view>
53 - 38 + </scroll-view>
54 </up-col> 39 </up-col>
55 40
56 <!-- 右侧:道路列表 (uview栅格列 + 原生滚动) --> 41 <!-- 右侧:道路列表 (uview栅格列 + 原生滚动) -->
@@ -67,13 +52,35 @@ @@ -67,13 +52,35 @@
67 :key="item.roadId" 52 :key="item.roadId"
68 @click="toNewPage(item.roadId, item.treeCount)" 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 </view> 84 </view>
78 </view> 85 </view>
79 </scroll-view> 86 </scroll-view>
@@ -193,32 +200,88 @@ const checkRoadDataValid = () =&gt; { @@ -193,32 +200,88 @@ const checkRoadDataValid = () =&gt; {
193 </script> 200 </script>
194 201
195 <style scoped lang="scss"> 202 <style scoped lang="scss">
196 -// 页面容器 满高布局 203 +// 页面容器 满高布局(页面底 #F4F6FA,设计稿 --page-bg)
197 .container { 204 .container {
198 height: 100%; 205 height: 100%;
199 display: flex; 206 display: flex;
200 flex-direction: column; 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 box-sizing: border-box; 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 .cate-layout { 273 .cate-layout {
211 flex: 1; 274 flex: 1;
  275 + min-height: 0;
212 width: 100%; 276 width: 100%;
213 - height: calc(100vh - 44px);  
214 -  
215 } 277 }
216 278
217 279
218 .cate-left { 280 .cate-left {
219 height: 100%; 281 height: 100%;
220 padding: 0; 282 padding: 0;
221 - background: #f8f8f8; 283 + background: #F4F6FA;
  284 + border-right: 1rpx solid #F0F0F0;
222 box-sizing: border-box; 285 box-sizing: border-box;
223 .left-scroll { 286 .left-scroll {
224 width: 100%; 287 width: 100%;
@@ -226,58 +289,132 @@ const checkRoadDataValid = () =&gt; { @@ -226,58 +289,132 @@ const checkRoadDataValid = () =&gt; {
226 } 289 }
227 // 左侧列表项 290 // 左侧列表项
228 .left-item { 291 .left-item {
229 - padding: 24rpx 12rpx;  
230 - font-size: 28rpx;  
231 - 292 + padding: 24rpx 20rpx;
  293 + font-size: 26rpx;
  294 + color: #4B5563;
232 white-space: nowrap; 295 white-space: nowrap;
233 overflow: hidden; 296 overflow: hidden;
234 text-overflow: ellipsis; 297 text-overflow: ellipsis;
235 box-sizing: border-box; 298 box-sizing: border-box;
236 } 299 }
237 - // 选中项高亮 主题色和你一致 #5f5fe2 300 + // 选中项高亮
238 .left-item.active { 301 .left-item.active {
239 background: #ffffff; 302 background: #ffffff;
240 - color: #5f5fe2; 303 + color: #2563EB;
241 font-weight: 500; 304 font-weight: 500;
242 - border-left: 4rpx solid #5f5fe2; 305 + border-left: 4rpx solid #2563EB;
243 } 306 }
244 } 307 }
245 308
246 .cate-right { 309 .cate-right {
247 height: 100%; 310 height: 100%;
248 - padding: 0 10rpx; 311 + padding: 0;
249 box-sizing: border-box; 312 box-sizing: border-box;
250 - background: #ffffff; 313 + background: #F4F6FA;
251 .right-scroll { 314 .right-scroll {
252 width: 100%; 315 width: 100%;
253 height: 100%; 316 height: 100%;
254 } 317 }
255 } 318 }
256 319
257 -// 道路列表容器 320 +// 道路列表容器:左右 20rpx、上 24rpx、下 48rpx 留白(设计稿 .right)
258 .road-list-wrap { 321 .road-list-wrap {
259 - //padding-bottom: 30rpx; 322 + padding: 24rpx 20rpx 48rpx;
260 } 323 }
261 324
262 -// 道路卡片样式 完全复用你的原版 325 +// 道路卡片:白底 16rpx 圆角 + 浅投影(设计稿 .tcard)
263 .card-wrap { 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 text-align: right; 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 display: flex; 408 display: flex;
279 - justify-content: space-between;  
280 align-items: center; 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 </style> 420 </style>
284 \ No newline at end of file 421 \ No newline at end of file
pages-sub/data/tree-archive/inspectDetail.vue
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 <style scoped> 14 <style scoped>
15 .inspect-detail { 15 .inspect-detail {
16 min-height: 100vh; 16 min-height: 100vh;
17 - background: #f5f7fa; 17 + background-color: #F4F6FA;
18 } 18 }
19 .content { 19 .content {
20 padding: 30rpx; 20 padding: 30rpx;
@@ -22,6 +22,6 @@ @@ -22,6 +22,6 @@
22 } 22 }
23 .empty-tip { 23 .empty-tip {
24 font-size: 14px; 24 font-size: 14px;
25 - color: #999; 25 + color: #909399;
26 } 26 }
27 </style> 27 </style>
28 \ No newline at end of file 28 \ No newline at end of file
pages-sub/data/tree-archive/logDetail.vue
1 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 <up-form :model="formData" ref="formRef" label-width="140rpx" border-bottom> 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 <up-form-item label="名称" prop="treetype" required> 10 <up-form-item label="名称" prop="treetype" required>
5 <up-input v-model="formData.treetype" border="none" readonly placeholder=""/> 11 <up-input v-model="formData.treetype" border="none" readonly placeholder=""/>
6 </up-form-item> 12 </up-form-item>
@@ -18,7 +24,7 @@ @@ -18,7 +24,7 @@
18 <up-form-item label="胸径" prop="dbh" required> 24 <up-form-item label="胸径" prop="dbh" required>
19 <up-input v-model="formData.dbh" maxlength="10" border="none" input-align="left" readonly placeholder=""/> 25 <up-input v-model="formData.dbh" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
20 <template #right> 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 </template> 28 </template>
23 </up-form-item> 29 </up-form-item>
24 </up-col> 30 </up-col>
@@ -26,7 +32,7 @@ @@ -26,7 +32,7 @@
26 <up-form-item label="高度" prop="treeheight"> 32 <up-form-item label="高度" prop="treeheight">
27 <up-input v-model="formData.treeheight" maxlength="10" border="none" input-align="left" readonly placeholder=""/> 33 <up-input v-model="formData.treeheight" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
28 <template #right> 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 </template> 36 </template>
31 </up-form-item> 37 </up-form-item>
32 </up-col> 38 </up-col>
@@ -101,7 +107,7 @@ @@ -101,7 +107,7 @@
101 <up-form-item label="干周" prop="weekday"> 107 <up-form-item label="干周" prop="weekday">
102 <up-input v-model="formData.weekday" maxlength="10" border="none" input-align="left" readonly placeholder=""/> 108 <up-input v-model="formData.weekday" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
103 <template #right> 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 </template> 111 </template>
106 </up-form-item> 112 </up-form-item>
107 </up-col> 113 </up-col>
@@ -114,7 +120,7 @@ @@ -114,7 +120,7 @@
114 <up-form-item label="东西冠幅" prop="canopyeastwest"> 120 <up-form-item label="东西冠幅" prop="canopyeastwest">
115 <up-input v-model="formData.canopyeastwest" maxlength="10" border="none" input-align="left" readonly placeholder=""/> 121 <up-input v-model="formData.canopyeastwest" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
116 <template #right> 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 </template> 124 </template>
119 </up-form-item> 125 </up-form-item>
120 </up-col> 126 </up-col>
@@ -122,7 +128,7 @@ @@ -122,7 +128,7 @@
122 <up-form-item label="南北冠幅" prop="canopysouthnorth"> 128 <up-form-item label="南北冠幅" prop="canopysouthnorth">
123 <up-input v-model="formData.canopysouthnorth" maxlength="10" border="none" input-align="left" readonly placeholder=""/> 129 <up-input v-model="formData.canopysouthnorth" maxlength="10" border="none" input-align="left" readonly placeholder=""/>
124 <template #right> 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 </template> 132 </template>
127 </up-form-item> 133 </up-form-item>
128 </up-col> 134 </up-col>
@@ -216,10 +222,54 @@ onReady(() =&gt; {}); @@ -216,10 +222,54 @@ onReady(() =&gt; {});
216 </script> 222 </script>
217 223
218 <style scoped lang="scss"> 224 <style scoped lang="scss">
  225 +/* 页面底色 + 留白(设计稿 --page-bg / .body) */
219 .page-container { 226 .page-container {
220 - padding: 25rpx; 227 + padding: 24rpx;
221 box-sizing: border-box; 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 .location-form-item { 275 .location-form-item {
@@ -227,13 +277,14 @@ onReady(() =&gt; {}); @@ -227,13 +277,14 @@ onReady(() =&gt; {});
227 } 277 }
228 278
229 :deep(.u-input__inner) { 279 :deep(.u-input__inner) {
230 - color: #333; 280 + font-size: 26rpx;
  281 + color: #4B5563;
231 background-color: transparent !important; 282 background-color: transparent !important;
232 } 283 }
233 284
234 .show-text { 285 .show-text {
235 - font-size: 28rpx;  
236 - color: #333; 286 + font-size: 26rpx;
  287 + color: #4B5563;
237 line-height: 80rpx; 288 line-height: 80rpx;
238 width: 100%; 289 width: 100%;
239 display: block; 290 display: block;
pages-sub/data/tree-archive/treeRecord.vue
@@ -33,20 +33,19 @@ @@ -33,20 +33,19 @@
33 <view class="record-list-right"> 33 <view class="record-list-right">
34 <view class="up-flex up-flex-items-center up-flex-between"> 34 <view class="up-flex up-flex-items-center up-flex-between">
35 <view class="u-line-1 treetypeName">{{ i.treetype }}</view> 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 </view> 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 </view> 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 </view> 43 </view>
46 </view> 44 </view>
47 </view> 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 </view> 49 </view>
51 </template> 50 </template>
52 </up-card> 51 </up-card>
@@ -111,62 +110,105 @@ const fetchData = async (pageNo, pageSize) =&gt; { @@ -111,62 +110,105 @@ const fetchData = async (pageNo, pageSize) =&gt; {
111 </script> 110 </script>
112 111
113 <style scoped lang="scss"> 112 <style scoped lang="scss">
114 -// ✅ 你的原始样式 一行没删、一行没改、全部保留 113 +/* 页面底色(设计稿 --page-bg) */
115 .page-container { 114 .page-container {
116 min-height: 100vh; 115 min-height: 100vh;
  116 + background-color: #F4F6FA;
  117 + box-sizing: border-box;
117 } 118 }
118 119
  120 +/* 列表:左右 24rpx 留白,卡片之间 24rpx(设计稿 .body) */
119 .record-wrap { 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 .record-list-left { 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 .record-list-right { 152 .record-list-right {
145 - margin-left: 20px; 153 + margin-left: 24rpx;
146 flex: 1; 154 flex: 1;
  155 + min-width: 0;
147 overflow: hidden; 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 display: flex; 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 </style> 214 </style>
173 \ No newline at end of file 215 \ No newline at end of file
pages-sub/msg/index.vue
@@ -21,10 +21,10 @@ @@ -21,10 +21,10 @@
21 <template #body> 21 <template #body>
22 <view class="card-body"> 22 <view class="card-body">
23 <view class="u-flex common-item-center common-justify-between" style="margin-top: 5px;"> 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 </view> 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 {{ item.templateContent || '无' }} 28 {{ item.templateContent || '无' }}
29 </view> 29 </view>
30 30
@@ -73,6 +73,13 @@ onShow( async () =&gt; { @@ -73,6 +73,13 @@ onShow( async () =&gt; {
73 73
74 <style lang="scss" scoped> 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 </style> 83 </style>
77 <script setup lang="ts"> 84 <script setup lang="ts">
78 </script> 85 </script>
79 \ No newline at end of file 86 \ No newline at end of file
pages-sub/problem/ai-manage/index.vue
@@ -6,8 +6,8 @@ @@ -6,8 +6,8 @@
6 <up-tabs 6 <up-tabs
7 v-model="activeTab" 7 v-model="activeTab"
8 :list="tabList" 8 :list="tabList"
9 - active-color="#1989fa"  
10 - inactive-color="#666" 9 + active-color="#2563EB"
  10 + inactive-color="#606266"
11 font-size="30rpx" 11 font-size="30rpx"
12 @click="handleTabChange" 12 @click="handleTabChange"
13 /> 13 />
@@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
51 <empty-view /> 51 <empty-view />
52 </template> 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 <up-card 56 <up-card
57 v-if="activeTab === 0" 57 v-if="activeTab === 0"
@@ -95,15 +95,16 @@ @@ -95,15 +95,16 @@
95 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view> 95 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
96 </view> 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 <template v-if="hasConfiguredActions(item)"> 100 <template v-if="hasConfiguredActions(item)">
100 <view 101 <view
101 v-for="action in item.configuredActions" 102 v-for="action in item.configuredActions"
102 :key="action.code" 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 @click.stop="handleUnifiedProcess(item, action)" 105 @click.stop="handleUnifiedProcess(item, action)"
105 >{{ action.name }}</view> 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 </template> 108 </template>
108 <!-- 未配置:沿用原有节点按钮 --> 109 <!-- 未配置:沿用原有节点按钮 -->
109 <template v-else> 110 <template v-else>
@@ -111,7 +112,7 @@ @@ -111,7 +112,7 @@
111 @click.stop="handleUnifiedReject(item)">回退</view> 112 @click.stop="handleUnifiedReject(item)">回退</view>
112 <view class="task-btn task-btn--primary" 113 <view class="task-btn task-btn--primary"
113 @click.stop="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</view> 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 </template> 116 </template>
116 </view> 117 </view>
117 </view> 118 </view>
@@ -130,9 +131,6 @@ @@ -130,9 +131,6 @@
130 > 131 >
131 <template #body> 132 <template #body>
132 <view class="card-body"> 133 <view class="card-body">
133 - <view class="common-custom-btn " style="--btn-top: 130px;" @click="handleDetail(item)">  
134 - 工单详情  
135 - </view>  
136 <view class="u-body-item u-flex"> 134 <view class="u-body-item u-flex">
137 <view class="u-body-item-title">工单编号:</view> 135 <view class="u-body-item-title">工单编号:</view>
138 <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view> 136 <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view>
@@ -165,6 +163,11 @@ @@ -165,6 +163,11 @@
165 <view class="u-body-item-title">提交时间:</view> 163 <view class="u-body-item-title">提交时间:</view>
166 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view> 164 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
167 </view> 165 </view>
  166 +
  167 + <!-- 底部操作:分隔线 + 查看详情(与工单管理列表统一) -->
  168 + <view class="card-foot">
  169 + <view class="foot-btn" @click="handleDetail(item)">工单详情</view>
  170 + </view>
168 </view> 171 </view>
169 </template> 172 </template>
170 </up-card> 173 </up-card>
@@ -276,7 +279,7 @@ import { @@ -276,7 +279,7 @@ import {
276 } from '@/api/regional-order-manage/regional-order-manage' 279 } from '@/api/regional-order-manage/regional-order-manage'
277 import { getTaskActions } from '@/api/work-order-manage/work-order-manage' 280 import { getTaskActions } from '@/api/work-order-manage/work-order-manage'
278 import { useUserStore } from '@/pinia/user'; 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 import { useUploadImgs } from '@/common/utils/useUploadImgs' 283 import { useUploadImgs } from '@/common/utils/useUploadImgs'
281 284
282 // ========== 全局实例 & 常量 ========== 285 // ========== 全局实例 & 常量 ==========
@@ -510,6 +513,16 @@ const getProcessButtonText = (item) =&gt; { @@ -510,6 +513,16 @@ const getProcessButtonText = (item) =&gt; {
510 const hasConfiguredActions = (item) => 513 const hasConfiguredActions = (item) =>
511 Array.isArray(item?.configuredActions) && item.configuredActions.length > 0 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 const handleUnifiedProcess = async (item, action = null) => { 527 const handleUnifiedProcess = async (item, action = null) => {
515 const actions = Array.isArray(item?.configuredActions) 528 const actions = Array.isArray(item?.configuredActions)
@@ -712,7 +725,7 @@ onShow(() =&gt; { @@ -712,7 +725,7 @@ onShow(() =&gt; {
712 <style scoped lang="scss"> 725 <style scoped lang="scss">
713 .page-container { 726 .page-container {
714 min-height: 100vh; 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,17 +756,47 @@ onShow(() =&gt; {
743 756
744 // 工单卡片样式 757 // 工单卡片样式
745 .order-card { 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 display: flex; 767 display: flex;
755 - flex-wrap: wrap;  
756 justify-content: flex-end; 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 margin-bottom: -10rpx; 800 margin-bottom: -10rpx;
758 } 801 }
759 802
@@ -761,20 +804,31 @@ onShow(() =&gt; { @@ -761,20 +804,31 @@ onShow(() =&gt; {
761 box-sizing: border-box; 804 box-sizing: border-box;
762 height: 56rpx; 805 height: 56rpx;
763 line-height: 56rpx; 806 line-height: 56rpx;
764 - padding: 0 24rpx;  
765 - margin: 0 0 10rpx 12rpx; 807 + padding: 0 12rpx;
766 border-radius: 8rpx; 808 border-radius: 8rpx;
767 font-size: 24rpx; 809 font-size: 24rpx;
768 color: #fff; 810 color: #fff;
  811 + text-align: center;
769 white-space: nowrap; 812 white-space: nowrap;
  813 + overflow: hidden;
  814 + text-overflow: ellipsis;
770 } 815 }
771 816
  817 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
772 .task-btn--primary { 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 .task-btn--success { 830 .task-btn--success {
777 - background-color: #5ac725; 831 + background-color: #078d0a;
778 } 832 }
779 833
780 .task-btn--warning { 834 .task-btn--warning {
@@ -789,7 +843,6 @@ onShow(() =&gt; { @@ -789,7 +843,6 @@ onShow(() =&gt; {
789 background-color: #909399; 843 background-color: #909399;
790 } 844 }
791 845
792 -  
793 // 弹窗公共样式 846 // 弹窗公共样式
794 .reject-modal-content, .accept-modal-content { 847 .reject-modal-content, .accept-modal-content {
795 width: 100%; 848 width: 100%;
@@ -800,7 +853,7 @@ onShow(() =&gt; { @@ -800,7 +853,7 @@ onShow(() =&gt; {
800 .upload-wrap { 853 .upload-wrap {
801 .upload-title { 854 .upload-title {
802 font-size: 28rpx; 855 font-size: 28rpx;
803 - color: #333; 856 + color: #1a1a1a;
804 margin-bottom: 10rpx; 857 margin-bottom: 10rpx;
805 } 858 }
806 } 859 }
pages-sub/problem/regional-order-manage/add-order.vue
1 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 - <view class="work-order-form-content commonPageLRpadding"> 3 + <view class="work-order-form-content">
4 <up-form 4 <up-form
5 label-position="left" 5 label-position="left"
6 :model="baseForm" 6 :model="baseForm"
7 ref="workOrderFormRef" 7 ref="workOrderFormRef"
8 labelWidth="200rpx" 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 <!-- 1. 工单位置(地图选择)【公共项】 --> 17 <!-- 1. 工单位置(地图选择)【公共项】 -->
11 <up-form-item 18 <up-form-item
12 label="工单位置" 19 label="工单位置"
13 prop="workLocation" 20 prop="workLocation"
14 border-bottom 21 border-bottom
15 required 22 required
  23 + class="form-item"
16 @click="chooseWorkLocation(); hideKeyboard()" 24 @click="chooseWorkLocation(); hideKeyboard()"
17 > 25 >
18 <up-input 26 <up-input
@@ -30,6 +38,7 @@ @@ -30,6 +38,7 @@
30 prop="problemDesc" 38 prop="problemDesc"
31 required 39 required
32 border-bottom 40 border-bottom
  41 + class="form-item"
33 > 42 >
34 <up-textarea 43 <up-textarea
35 placeholder="请输入情况描述(最多200字)" 44 placeholder="请输入情况描述(最多200字)"
@@ -42,7 +51,7 @@ @@ -42,7 +51,7 @@
42 </up-form-item> 51 </up-form-item>
43 52
44 <!-- 3. 问题照片【公共项】 --> 53 <!-- 3. 问题照片【公共项】 -->
45 - <up-form-item label="问题照片" prop="problemImgs" required > 54 + <up-form-item label="问题照片" prop="problemImgs" required class="form-item">
46 <up-upload 55 <up-upload
47 :file-list="problemImgs.imgList.value || []" 56 :file-list="problemImgs.imgList.value || []"
48 @after-read="problemImgs.uploadImgs" 57 @after-read="problemImgs.uploadImgs"
@@ -55,6 +64,7 @@ @@ -55,6 +64,7 @@
55 :size-type="problemImgs.uploadConfig.sizeType" 64 :size-type="problemImgs.uploadConfig.sizeType"
56 ></up-upload> 65 ></up-upload>
57 </up-form-item> 66 </up-form-item>
  67 + </view>
58 68
59 <!-- 多组派单区域 --> 69 <!-- 多组派单区域 -->
60 <view class="dispatch-list-wrap"> 70 <view class="dispatch-list-wrap">
@@ -827,45 +837,111 @@ if (hasRepeat) { @@ -827,45 +837,111 @@ if (hasRepeat) {
827 </script> 837 </script>
828 838
829 <style lang="scss" scoped> 839 <style lang="scss" scoped>
  840 +/* 统一卡片样式(与工单表单页一致) */
830 .page-container { 841 .page-container {
831 min-height: 100vh; 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 .work-order-form-content { 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 .dispatch-list-wrap { 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 .dispatch-title { 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 .dispatch-item { 929 .dispatch-item {
855 position: relative; 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 .item-head { 937 .item-head {
863 display: flex; 938 display: flex;
864 justify-content: space-between; 939 justify-content: space-between;
865 align-items: center; 940 align-items: center;
866 - margin-bottom: 16rpx;  
867 - font-size: 28rpx; 941 + padding: 20rpx 0 8rpx;
  942 + font-size: 30rpx;
868 font-weight: 500; 943 font-weight: 500;
  944 + color: #1F2937;
869 } 945 }
870 946
871 .close-icon { 947 .close-icon {
@@ -875,6 +951,20 @@ if (hasRepeat) { @@ -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 .add-dispatch-btn-wrap { 968 .add-dispatch-btn-wrap {
879 margin: 20rpx 0; 969 margin: 20rpx 0;
880 } 970 }
pages-sub/problem/regional-order-manage/add-patrol-order.vue
1 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 - <view class="work-order-form-content commonPageLRpadding"> 3 + <view class="work-order-form-content">
4 <up-form label-position="left" :model="workOrderForm" ref="workOrderFormRef" labelWidth="200rpx"> 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 <!-- 1. 工单位置(地图选择) --> 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 @click="chooseWorkLocation(); hideKeyboard()"> 13 @click="chooseWorkLocation(); hideKeyboard()">
8 <up-input v-model="workOrderForm.workLocation" border="none" readonly suffix-icon="map-fill" 14 <up-input v-model="workOrderForm.workLocation" border="none" readonly suffix-icon="map-fill"
9 placeholder="点击选择工单位置"></up-input> 15 placeholder="点击选择工单位置"></up-input>
10 </up-form-item> 16 </up-form-item>
11 17
12 <!-- 2. 问题类型(下拉框) --> 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 @click="handleActionSheetOpen('orderName'); hideKeyboard()"> 20 @click="handleActionSheetOpen('orderName'); hideKeyboard()">
15 <up-input v-model="workOrderForm.orderName" disabled disabled-color="#ffffff" placeholder="请选择问题类型" 21 <up-input v-model="workOrderForm.orderName" disabled disabled-color="#ffffff" placeholder="请选择问题类型"
16 border="none"></up-input> 22 border="none"></up-input>
@@ -20,18 +26,25 @@ @@ -20,18 +26,25 @@
20 </up-form-item> 26 </up-form-item>
21 27
22 <!-- 3. 情况描述(文本域) --> 28 <!-- 3. 情况描述(文本域) -->
23 - <up-form-item label="情况描述" prop="problemDesc" required> 29 + <up-form-item label="情况描述" prop="problemDesc" required class="form-item">
24 <up-textarea placeholder="请输入情况描述(最多200字)" v-model.trim="workOrderForm.problemDesc" count maxlength="200" 30 <up-textarea placeholder="请输入情况描述(最多200字)" v-model.trim="workOrderForm.problemDesc" count maxlength="200"
25 rows="4" @blur="() => workOrderFormRef.validateField('problemDesc')"></up-textarea> 31 rows="4" @blur="() => workOrderFormRef.validateField('problemDesc')"></up-textarea>
26 </up-form-item> 32 </up-form-item>
  33 + </view>
27 34
28 <!-- 4. 问题照片 --> 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 </up-form> 49 </up-form>
37 </view> 50 </view>
@@ -352,13 +365,65 @@ const submitWorkOrder = async () =&gt; { @@ -352,13 +365,65 @@ const submitWorkOrder = async () =&gt; {
352 </script> 365 </script>
353 366
354 <style lang="scss" scoped> 367 <style lang="scss" scoped>
355 -// 全局页面样式 368 +/* 统一卡片样式(与工单表单页一致) */
356 .page-container { 369 .page-container {
357 min-height: 100vh; 370 min-height: 100vh;
  371 + padding-bottom: 200rpx;
  372 + background-color: #F4F6FA;
  373 + box-sizing: border-box;
358 } 374 }
359 375
360 -// 工单表单内容容器  
361 .work-order-form-content { 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 </style> 429 </style>
365 \ No newline at end of file 430 \ No newline at end of file
pages-sub/problem/regional-order-manage/distribution-order.vue
1 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 - <view class="work-order-form-content commonPageLRpadding"> 3 + <view class="work-order-form-content">
4 <up-form label-position="left" :model="workOrderForm" ref="workOrderFormRef" labelWidth="200rpx"> 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 <!-- 1. 工单位置(地图选择)【赋值回显 + 完全禁止修改】 --> 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 <up-input v-model="workOrderForm.workLocation" border="none" disabled placeholder="暂无工单位置"></up-input> 14 <up-input v-model="workOrderForm.workLocation" border="none" disabled placeholder="暂无工单位置"></up-input>
8 </up-form-item> 15 </up-form-item>
9 16
10 <!-- 2. 问题类型(下拉框)【赋值回显 + 完全禁止修改】 --> 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 <up-input v-model="workOrderForm.orderName" disabled placeholder="暂无问题类型" border="none"></up-input> 19 <up-input v-model="workOrderForm.orderName" disabled placeholder="暂无问题类型" border="none"></up-input>
13 </up-form-item> 20 </up-form-item>
14 21
15 <!-- 3. 情况描述(文本域)【赋值回显 + 完全禁止修改】 --> 22 <!-- 3. 情况描述(文本域)【赋值回显 + 完全禁止修改】 -->
16 - <up-form-item label="情况描述" prop="problemDesc" required> 23 + <up-form-item label="情况描述" prop="problemDesc" required class="form-item">
17 <up-textarea v-model.trim="workOrderForm.problemDesc" count maxlength="200" rows="4" disabled 24 <up-textarea v-model.trim="workOrderForm.problemDesc" count maxlength="200" rows="4" disabled
18 disabled-color="#333333" placeholder="暂无情况描述"></up-textarea> 25 disabled-color="#333333" placeholder="暂无情况描述"></up-textarea>
19 </up-form-item> 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 <up-radio-group v-model="workOrderForm.busiLineCn" placement="row" @change="handleBusiLineChange"> 51 <up-radio-group v-model="workOrderForm.busiLineCn" placement="row" @change="handleBusiLineChange">
35 <up-radio v-for="item in busiLineOptions" :key="item.name" :label="item.name" 52 <up-radio v-for="item in busiLineOptions" :key="item.name" :label="item.name"
36 :name="item.name"></up-radio> 53 :name="item.name"></up-radio>
@@ -38,7 +55,7 @@ @@ -38,7 +55,7 @@
38 </up-form-item> 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 @click="handleActionSheetOpen('roadName'); hideKeyboard()"> 59 @click="handleActionSheetOpen('roadName'); hideKeyboard()">
43 <up-input v-model="workOrderForm.roadName" readonly disabled-color="#ffffff" placeholder="请先选择工单位置" 60 <up-input v-model="workOrderForm.roadName" readonly disabled-color="#ffffff" placeholder="请先选择工单位置"
44 border="none"></up-input> 61 border="none"></up-input>
@@ -48,7 +65,7 @@ @@ -48,7 +65,7 @@
48 </up-form-item> 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 @click="handleActionSheetOpen('pressingType'); hideKeyboard()"> 69 @click="handleActionSheetOpen('pressingType'); hideKeyboard()">
53 <up-input v-model="workOrderForm.pressingTypeName" disabled disabled-color="#ffffff" placeholder="请选择紧急程度" 70 <up-input v-model="workOrderForm.pressingTypeName" disabled disabled-color="#ffffff" placeholder="请选择紧急程度"
54 border="none"></up-input> 71 border="none"></up-input>
@@ -56,18 +73,19 @@ @@ -56,18 +73,19 @@
56 <up-icon name="arrow-right" size="16"></up-icon> 73 <up-icon name="arrow-right" size="16"></up-icon>
57 </template> 74 </template>
58 </up-form-item> 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 </up-form> 89 </up-form>
72 </view> 90 </view>
73 91
@@ -516,28 +534,65 @@ const submitWorkOrder = async () =&gt; { @@ -516,28 +534,65 @@ const submitWorkOrder = async () =&gt; {
516 </script> 534 </script>
517 535
518 <style lang="scss" scoped> 536 <style lang="scss" scoped>
519 -// 全局页面样式 537 +/* 统一卡片样式(与工单表单页一致) */
520 .page-container { 538 .page-container {
521 min-height: 100vh; 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 .work-order-form-content { 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 </style> 598 </style>
544 \ No newline at end of file 599 \ No newline at end of file
pages-sub/problem/regional-order-manage/index.vue
@@ -6,8 +6,8 @@ @@ -6,8 +6,8 @@
6 <up-tabs 6 <up-tabs
7 v-model="activeTab" 7 v-model="activeTab"
8 :list="tabList" 8 :list="tabList"
9 - active-color="#1989fa"  
10 - inactive-color="#666" 9 + active-color="#2563EB"
  10 + inactive-color="#606266"
11 font-size="30rpx" 11 font-size="30rpx"
12 @click="handleTabChange" 12 @click="handleTabChange"
13 /> 13 />
@@ -107,15 +107,16 @@ @@ -107,15 +107,16 @@
107 </view> 107 </view>
108 108
109 <!-- 待办工单(0):已配置工作流动作时按配置逐个渲染按钮,点击直接执行对应动作 --> 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 <template v-if="hasConfiguredActions(item)"> 112 <template v-if="hasConfiguredActions(item)">
112 <view 113 <view
113 v-for="action in item.configuredActions" 114 v-for="action in item.configuredActions"
114 :key="action.code" 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 @click.stop="handleUnifiedProcess(item, action)" 117 @click.stop="handleUnifiedProcess(item, action)"
117 >{{ action.name }}</view> 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 </template> 120 </template>
120 <!-- 未配置:沿用原有节点按钮 --> 121 <!-- 未配置:沿用原有节点按钮 -->
121 <template v-else> 122 <template v-else>
@@ -125,7 +126,7 @@ @@ -125,7 +126,7 @@
125 @click.stop="handleRenew(item)">重新提交</view> 126 @click.stop="handleRenew(item)">重新提交</view>
126 <view class="task-btn task-btn--primary" 127 <view class="task-btn task-btn--primary"
127 @click.stop="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</view> 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 </template> 130 </template>
130 </view> 131 </view>
131 132
@@ -241,7 +242,7 @@ import { @@ -241,7 +242,7 @@ import {
241 } from '@/api/regional-order-manage/regional-order-manage' 242 } from '@/api/regional-order-manage/regional-order-manage'
242 import { getTaskActions } from '@/api/work-order-manage/work-order-manage' 243 import { getTaskActions } from '@/api/work-order-manage/work-order-manage'
243 import { useUserStore } from '@/pinia/user'; 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 import { useUploadImgs } from '@/common/utils/useUploadImgs' 246 import { useUploadImgs } from '@/common/utils/useUploadImgs'
246 247
247 // ========== 全局实例 & 常量 ========== 248 // ========== 全局实例 & 常量 ==========
@@ -491,6 +492,17 @@ const getProcessButtonText = (item) =&gt; { @@ -491,6 +492,17 @@ const getProcessButtonText = (item) =&gt; {
491 const hasConfiguredActions = (item) => 492 const hasConfiguredActions = (item) =>
492 Array.isArray(item?.configuredActions) && item.configuredActions.length > 0 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 const handleUnifiedProcess = async (item, action = null) => { 507 const handleUnifiedProcess = async (item, action = null) => {
496 const actions = Array.isArray(item?.configuredActions) 508 const actions = Array.isArray(item?.configuredActions)
@@ -576,7 +588,6 @@ const handleProcess = async (item) =&gt; { @@ -576,7 +588,6 @@ const handleProcess = async (item) =&gt; {
576 }); 588 });
577 } 589 }
578 590
579 -  
580 // 验收弹窗 591 // 验收弹窗
581 else if (['巡查员验收', '养护组长验收'].includes(stepName)) { 592 else if (['巡查员验收', '养护组长验收'].includes(stepName)) {
582 currentAcceptItem.value = item; 593 currentAcceptItem.value = item;
@@ -702,7 +713,7 @@ onLoad(() =&gt; { @@ -702,7 +713,7 @@ onLoad(() =&gt; {
702 <style scoped lang="scss"> 713 <style scoped lang="scss">
703 .page-container { 714 .page-container {
704 min-height: 100vh; 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,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 .common-card-list { 748 .common-card-list {
736 - padding: calc(var(--status-bar-height) + 140rpx) 0 30rpx; 749 + padding: 216rpx 0 180rpx;
737 box-sizing: border-box; 750 box-sizing: border-box;
738 } 751 }
739 752
740 // 工单卡片样式 753 // 工单卡片样式
741 .order-card { 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 .task-btn-row { 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 margin-bottom: -10rpx; 767 margin-bottom: -10rpx;
754 } 768 }
755 769
@@ -757,20 +771,31 @@ onLoad(() =&gt; { @@ -757,20 +771,31 @@ onLoad(() =&gt; {
757 box-sizing: border-box; 771 box-sizing: border-box;
758 height: 56rpx; 772 height: 56rpx;
759 line-height: 56rpx; 773 line-height: 56rpx;
760 - padding: 0 24rpx;  
761 - margin: 0 0 10rpx 12rpx; 774 + padding: 0 12rpx;
762 border-radius: 8rpx; 775 border-radius: 8rpx;
763 font-size: 24rpx; 776 font-size: 24rpx;
764 color: #fff; 777 color: #fff;
  778 + text-align: center;
765 white-space: nowrap; 779 white-space: nowrap;
  780 + overflow: hidden;
  781 + text-overflow: ellipsis;
766 } 782 }
767 783
  784 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
768 .task-btn--primary { 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 .task-btn--success { 797 .task-btn--success {
773 - background-color: #5ac725; 798 + background-color: #078d0a;
774 } 799 }
775 800
776 .task-btn--warning { 801 .task-btn--warning {
@@ -785,7 +810,6 @@ onLoad(() =&gt; { @@ -785,7 +810,6 @@ onLoad(() =&gt; {
785 background-color: #909399; 810 background-color: #909399;
786 } 811 }
787 812
788 -  
789 // 新增样式:解决按钮和文字间距、排版问题 813 // 新增样式:解决按钮和文字间距、排版问题
790 .flex-1 { flex: 1; } 814 .flex-1 { flex: 1; }
791 .text-right { text-align: right; } 815 .text-right { text-align: right; }
@@ -801,7 +825,7 @@ onLoad(() =&gt; { @@ -801,7 +825,7 @@ onLoad(() =&gt; {
801 .upload-wrap { 825 .upload-wrap {
802 .upload-title { 826 .upload-title {
803 font-size: 28rpx; 827 font-size: 28rpx;
804 - color: #333; 828 + color: #1a1a1a;
805 margin-bottom: 10rpx; 829 margin-bottom: 10rpx;
806 } 830 }
807 } 831 }
pages-sub/problem/regional-order-manage/list-detail.vue
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 v-if="loading" 5 v-if="loading"
6 :loading="true" 6 :loading="true"
7 title="加载中..." 7 title="加载中..."
8 - color="#3c9cff" 8 + color="#2563EB"
9 ></up-loading-page> 9 ></up-loading-page>
10 10
11 <view v-else class="main-content" :class="'pb-rows-' + actionBarRows"> 11 <view v-else class="main-content" :class="'pb-rows-' + actionBarRows">
@@ -16,8 +16,8 @@ @@ -16,8 +16,8 @@
16 :list="topTabList" 16 :list="topTabList"
17 :scrollable="false" 17 :scrollable="false"
18 sticky 18 sticky
19 - active-color="#3c9cff"  
20 - inactive-color="#666" 19 + active-color="#2563EB"
  20 + inactive-color="#606266"
21 class="top-tabs" 21 class="top-tabs"
22 @click="activeTopTabClick" 22 @click="activeTopTabClick"
23 ></up-tabs> 23 ></up-tabs>
@@ -141,8 +141,8 @@ @@ -141,8 +141,8 @@
141 v-model="activeImgTab" 141 v-model="activeImgTab"
142 :list="imgTabList" 142 :list="imgTabList"
143 :scrollable="false" 143 :scrollable="false"
144 - active-color="#3c9cff"  
145 - inactive-color="#666" 144 + active-color="#2563EB"
  145 + inactive-color="#606266"
146 class="img-tabs" 146 class="img-tabs"
147 ></up-tabs> 147 ></up-tabs>
148 <view class="img-tab-content"> 148 <view class="img-tab-content">
@@ -166,8 +166,8 @@ @@ -166,8 +166,8 @@
166 :list="processData.activityNodes" 166 :list="processData.activityNodes"
167 :current="getCurrentStepIndex()" 167 :current="getCurrentStepIndex()"
168 direction="column" 168 direction="column"
169 - active-color="#3c9cff"  
170 - inactive-color="#999" 169 + active-color="#2563EB"
  170 + inactive-color="#909399"
171 class="vertical-steps" 171 class="vertical-steps"
172 > 172 >
173 <template> 173 <template>
@@ -178,7 +178,7 @@ @@ -178,7 +178,7 @@
178 <template #content> 178 <template #content>
179 <view class="step-content-wrap"> 179 <view class="step-content-wrap">
180 <view class="step-title"> 180 <view class="step-title">
181 - {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }} 181 + {{ item.name }}
182 </view> 182 </view>
183 <view class="step-desc"> 183 <view class="step-desc">
184 <view class="operator-name up-line-1" v-if="item.tasks"> 184 <view class="operator-name up-line-1" v-if="item.tasks">
@@ -225,17 +225,18 @@ @@ -225,17 +225,18 @@
225 <!-- 底部操作按钮 --> 225 <!-- 底部操作按钮 -->
226 <view v-if="activeTab === '0' && (configuredActions || nextStepMap[orderDetail.taskKey])" 226 <view v-if="activeTab === '0' && (configuredActions || nextStepMap[orderDetail.taskKey])"
227 class="fixed-bottom-btn-wrap order-action-bar"> 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 <view 231 <view
231 v-for="action in configuredActions" 232 v-for="action in configuredActions"
232 :key="action.code" 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 @click.stop="handleUnifiedProcess(orderDetail, action)" 235 @click.stop="handleUnifiedProcess(orderDetail, action)"
235 >{{ action.name }}</view> 236 >{{ action.name }}</view>
236 </view> 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 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning" 240 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning"
240 @click.stop="handleUnifiedReject(orderDetail)">回退</view> 241 @click.stop="handleUnifiedReject(orderDetail)">回退</view>
241 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success" 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,7 +338,7 @@ import { timeFormat } from &#39;@/uni_modules/uview-plus&#39;
337 import { getApprovalDetail,workOrderDetailByID } from '@/api/regional-order-manage/regional-order-manage' 338 import { getApprovalDetail,workOrderDetailByID } from '@/api/regional-order-manage/regional-order-manage'
338 import { getTaskActions } from '@/api/work-order-manage/work-order-manage' 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 import { useUploadImgs } from '@/common/utils/useUploadImgs' 342 import { useUploadImgs } from '@/common/utils/useUploadImgs'
342 import { useUserStore } from '@/pinia/user' 343 import { useUserStore } from '@/pinia/user'
343 344
@@ -523,15 +524,20 @@ const showRejectButton = computed(() =&gt; { @@ -523,15 +524,20 @@ const showRejectButton = computed(() =&gt; {
523 const hasConfiguredActions = computed(() => 524 const hasConfiguredActions = computed(() =>
524 Array.isArray(configuredActions.value) && configuredActions.value.length > 0) 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 const actionBarRows = computed(() => { 536 const actionBarRows = computed(() => {
528 if (hasConfiguredActions.value) { 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,33 +930,47 @@ onLoad((options: any) =&gt; {
924 <style scoped lang="scss"> 930 <style scoped lang="scss">
925 .page-container { 931 .page-container {
926 min-height: 100vh; 932 min-height: 100vh;
927 - background-color: #f5f5f5; 933 + background-color: #F4F6FA;
  934 + box-sizing: border-box;
928 } 935 }
929 936
930 .main-content { 937 .main-content {
931 padding-bottom: 80rpx; 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 .detail-content { 947 .detail-content {
935 .detail-cell-group { 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 .empty-text { 955 .empty-text {
940 - color: #999;  
941 - font-size: 26rpx; 956 + color: #909399;
  957 + font-size: 28rpx;
942 } 958 }
943 } 959 }
944 960
945 .img-tabs-block { 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 .img-tab-content { 967 .img-tab-content {
948 padding: 20rpx 15px; 968 padding: 20rpx 15px;
949 text-align: center; 969 text-align: center;
950 .empty-img-text { 970 .empty-img-text {
951 height: 75px; 971 height: 75px;
952 line-height: 75px; 972 line-height: 75px;
953 - color: #999; 973 + color: #909399;
954 font-size: 28rpx; 974 font-size: 28rpx;
955 } 975 }
956 } 976 }
@@ -961,9 +981,11 @@ onLoad((options: any) =&gt; { @@ -961,9 +981,11 @@ onLoad((options: any) =&gt; {
961 margin-top: 100rpx; 981 margin-top: 100rpx;
962 } 982 }
963 .vertical-steps { 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 display: flex; 989 display: flex;
968 flex-direction: column; 990 flex-direction: column;
969 gap: 20rpx; 991 gap: 20rpx;
@@ -974,12 +996,12 @@ onLoad((options: any) =&gt; { @@ -974,12 +996,12 @@ onLoad((options: any) =&gt; {
974 .step-title { 996 .step-title {
975 font-size: 30rpx; 997 font-size: 30rpx;
976 font-weight: 600; 998 font-weight: 600;
977 - color: #333; 999 + color: #1a1a1a;
978 margin-bottom: 12rpx; 1000 margin-bottom: 12rpx;
979 } 1001 }
980 .step-desc { 1002 .step-desc {
981 font-size: 24rpx; 1003 font-size: 24rpx;
982 - color: #666; 1004 + color: #606266;
983 line-height: 1.6; 1005 line-height: 1.6;
984 .processing-tag { 1006 .processing-tag {
985 color: #f59c26; 1007 color: #f59c26;
@@ -1001,8 +1023,8 @@ onLoad((options: any) =&gt; { @@ -1001,8 +1023,8 @@ onLoad((options: any) =&gt; {
1001 } 1023 }
1002 1024
1003 .upload-title { 1025 .upload-title {
1004 - font-size: 26rpx;  
1005 - color: #666; 1026 + font-size: 28rpx;
  1027 + color: #606266;
1006 margin-bottom: 10rpx; 1028 margin-bottom: 10rpx;
1007 } 1029 }
1008 1030
@@ -1025,8 +1047,7 @@ onLoad((options: any) =&gt; { @@ -1025,8 +1047,7 @@ onLoad((options: any) =&gt; {
1025 height: 70px !important; 1047 height: 70px !important;
1026 } 1048 }
1027 1049
1028 -// 底部动作按钮:动作多时自动换行  
1029 -// 底部操作栏:白底 + 顶部投影,按钮每行最多 3 个,避免多动作时整屏遮挡工单详情 1050 +// 底部操作栏:白底 + 顶部投影,按钮每行最多 5 个,避免多动作时整屏遮挡工单详情
1030 .order-action-bar { 1051 .order-action-bar {
1031 background-color: #fff; 1052 background-color: #fff;
1032 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06); 1053 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
@@ -1035,21 +1056,20 @@ onLoad((options: any) =&gt; { @@ -1035,21 +1056,20 @@ onLoad((options: any) =&gt; {
1035 padding-bottom: calc(10rpx + env(safe-area-inset-bottom)); 1056 padding-bottom: calc(10rpx + env(safe-area-inset-bottom));
1036 } 1057 }
1037 1058
  1059 +// 底部操作按钮:单按钮占一半宽度,多个按钮等分,每行最多 5 个
1038 .order-action-row { 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 .order-action-btn { 1066 .order-action-btn {
1045 box-sizing: border-box; 1067 box-sizing: border-box;
1046 - width: calc((100% - 36rpx) / 3);  
1047 height: 68rpx; 1068 height: 68rpx;
1048 line-height: 68rpx; 1069 line-height: 68rpx;
1049 - margin: 6rpx;  
1050 padding: 0 8rpx; 1070 padding: 0 8rpx;
1051 border-radius: 8rpx; 1071 border-radius: 8rpx;
1052 - font-size: 26rpx; 1072 + font-size: 28rpx;
1053 text-align: center; 1073 text-align: center;
1054 color: #fff; 1074 color: #fff;
1055 white-space: nowrap; 1075 white-space: nowrap;
@@ -1057,17 +1077,21 @@ onLoad((options: any) =&gt; { @@ -1057,17 +1077,21 @@ onLoad((options: any) =&gt; {
1057 text-overflow: ellipsis; 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 .order-action-btn--success { 1093 .order-action-btn--success {
1070 - background-color: #5ac725; 1094 + background-color: #078d0a;
1071 } 1095 }
1072 1096
1073 .order-action-btn--warning { 1097 .order-action-btn--warning {
pages-sub/problem/regional-order-manage/list.vue
@@ -478,7 +478,7 @@ onMounted(async () =&gt; { @@ -478,7 +478,7 @@ onMounted(async () =&gt; {
478 <style scoped lang="scss"> 478 <style scoped lang="scss">
479 .page-container { 479 .page-container {
480 min-height: 100vh; 480 min-height: 100vh;
481 - background-color: #fafafa; 481 + background-color: #F4F6FA;
482 } 482 }
483 483
484 .header-wrap { 484 .header-wrap {
@@ -498,8 +498,8 @@ onMounted(async () =&gt; { @@ -498,8 +498,8 @@ onMounted(async () =&gt; {
498 right: 0; 498 right: 0;
499 z-index: 99; /* 高于列表,防止被遮挡 */ 499 z-index: 99; /* 高于列表,防止被遮挡 */
500 background: #e4dc8e; 500 background: #e4dc8e;
501 - color: #333;  
502 - font-size: 26rpx; 501 + color: #1a1a1a;
  502 + font-size: 28rpx;
503 padding: 14rpx 20rpx; 503 padding: 14rpx 20rpx;
504 text-align: center; 504 text-align: center;
505 } 505 }
@@ -571,10 +571,10 @@ onMounted(async () =&gt; { @@ -571,10 +571,10 @@ onMounted(async () =&gt; {
571 } 571 }
572 572
573 .order-card { 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,7 +593,7 @@ onMounted(async () =&gt; {
593 .upload-wrap { 593 .upload-wrap {
594 .upload-title { 594 .upload-title {
595 font-size: 28rpx; 595 font-size: 28rpx;
596 - color: #333; 596 + color: #1a1a1a;
597 margin-bottom: 10rpx; 597 margin-bottom: 10rpx;
598 } 598 }
599 } 599 }
pages-sub/problem/regional-order-manage/order-detail.vue
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 v-if="loading" 5 v-if="loading"
6 :loading="true" 6 :loading="true"
7 title="加载中..." 7 title="加载中..."
8 - color="#3c9cff" 8 + color="#2563EB"
9 ></up-loading-page> 9 ></up-loading-page>
10 10
11 <!-- 主内容容器 --> 11 <!-- 主内容容器 -->
@@ -17,8 +17,8 @@ @@ -17,8 +17,8 @@
17 :list="topTabList" 17 :list="topTabList"
18 :scrollable="false" 18 :scrollable="false"
19 sticky 19 sticky
20 - active-color="#3c9cff"  
21 - inactive-color="#666" 20 + active-color="#2563EB"
  21 + inactive-color="#606266"
22 class="top-tabs" 22 class="top-tabs"
23 @click="activeTopTabClick" 23 @click="activeTopTabClick"
24 ></up-tabs> 24 ></up-tabs>
@@ -156,8 +156,8 @@ @@ -156,8 +156,8 @@
156 v-model="activeImgTab" 156 v-model="activeImgTab"
157 :list="imgTabList" 157 :list="imgTabList"
158 :scrollable="false" 158 :scrollable="false"
159 - active-color="#3c9cff"  
160 - inactive-color="#666" 159 + active-color="#2563EB"
  160 + inactive-color="#606266"
161 class="img-tabs" 161 class="img-tabs"
162 ></up-tabs> 162 ></up-tabs>
163 163
@@ -184,8 +184,8 @@ @@ -184,8 +184,8 @@
184 :list="processData.activityNodes" 184 :list="processData.activityNodes"
185 :current="getCurrentStepIndex()" 185 :current="getCurrentStepIndex()"
186 direction="column" 186 direction="column"
187 - active-color="#3c9cff"  
188 - inactive-color="#999" 187 + active-color="#2563EB"
  188 + inactive-color="#909399"
189 class="vertical-steps" 189 class="vertical-steps"
190 > 190 >
191 <template> 191 <template>
@@ -198,7 +198,7 @@ @@ -198,7 +198,7 @@
198 <view class="step-content-wrap"> 198 <view class="step-content-wrap">
199 <!-- 1. 原标题内容:节点名称 + 操作人 --> 199 <!-- 1. 原标题内容:节点名称 + 操作人 -->
200 <view class="step-title"> 200 <view class="step-title">
201 - {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }} 201 + {{ item.name }}
202 </view> 202 </view>
203 203
204 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) --> 204 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) -->
@@ -255,17 +255,18 @@ @@ -255,17 +255,18 @@
255 <!-- activeTab==0的时候才出现, 也就是待办 --> 255 <!-- activeTab==0的时候才出现, 也就是待办 -->
256 <view v-if="activeTab==0&&(configuredActions||nextStepMap[orderDetail.taskKey])" 256 <view v-if="activeTab==0&&(configuredActions||nextStepMap[orderDetail.taskKey])"
257 class="fixed-bottom-btn-wrap order-action-bar"> 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 <view 261 <view
261 v-for="action in configuredActions" 262 v-for="action in configuredActions"
262 :key="action.code" 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 @click.stop="handleUnifiedProcess(orderDetail, action)" 265 @click.stop="handleUnifiedProcess(orderDetail, action)"
265 >{{ action.name }}</view> 266 >{{ action.name }}</view>
266 </view> 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 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning" 270 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning"
270 @click.stop="handleUnifiedReject(orderDetail)">回退</view> 271 @click.stop="handleUnifiedReject(orderDetail)">回退</view>
271 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success" 272 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success"
@@ -381,7 +382,7 @@ import { @@ -381,7 +382,7 @@ import {
381 dcyUniversalApproval, 382 dcyUniversalApproval,
382 aiUniversalApproval 383 aiUniversalApproval
383 } from '@/api/regional-order-manage/regional-order-manage'; 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 import {getTaskActions} from '@/api/work-order-manage/work-order-manage'; 386 import {getTaskActions} from '@/api/work-order-manage/work-order-manage';
386 import {useUploadImgs} from '@/common/utils/useUploadImgs' 387 import {useUploadImgs} from '@/common/utils/useUploadImgs'
387 import { useUserStore } from '@/pinia/user'; 388 import { useUserStore } from '@/pinia/user';
@@ -392,7 +393,6 @@ const USER_ROLES = userStore.userInfo?.roles || []; @@ -392,7 +393,6 @@ const USER_ROLES = userStore.userInfo?.roles || [];
392 // ========== 页面通信事件通道 解决未定义BUG ========== 393 // ========== 页面通信事件通道 解决未定义BUG ==========
393 const eventChannel = ref<any>(null); 394 const eventChannel = ref<any>(null);
394 395
395 -  
396 // ========== 公共封装方法 (和列表页完全一致) ========== 396 // ========== 公共封装方法 (和列表页完全一致) ==========
397 /** 397 /**
398 * 统一提示方法 398 * 统一提示方法
@@ -593,15 +593,20 @@ const showRejectButton = computed(() =&gt; { @@ -593,15 +593,20 @@ const showRejectButton = computed(() =&gt; {
593 const hasConfiguredActions = computed(() => 593 const hasConfiguredActions = computed(() =>
594 Array.isArray(configuredActions.value) && configuredActions.value.length > 0) 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 const actionBarRows = computed(() => { 605 const actionBarRows = computed(() => {
598 if (hasConfiguredActions.value) { 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,6 +1006,8 @@ onShow(() =&gt; {});
1001 // 全局样式 1006 // 全局样式
1002 .page-container { 1007 .page-container {
1003 min-height: 100vh; 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,29 +1019,39 @@ onShow(() =&gt; {});
1012 .top-tabs { 1019 .top-tabs {
1013 } 1020 }
1014 1021
1015 -// Tab内容区 1022 +// Tab内容区:左右 24rpx 留白(设计稿 .body)
1016 .tab-content { 1023 .tab-content {
  1024 + padding: 0 24rpx;
  1025 + box-sizing: border-box;
1017 } 1026 }
1018 1027
1019 // 工单详情内容 1028 // 工单详情内容
1020 .detail-content { 1029 .detail-content {
  1030 + // 白色卡片:16rpx 圆角 + 卡片阴影(设计稿 .card)
1021 .detail-cell-group { 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 .cell-content-wrap { 1039 .cell-content-wrap {
1027 } 1040 }
1028 1041
1029 .empty-text { 1042 .empty-text {
1030 - color: #999;  
1031 - font-size: 26rpx; 1043 + color: #909399;
  1044 + font-size: 28rpx;
1032 } 1045 }
1033 } 1046 }
1034 1047
1035 // 图片分类Tabs区块 1048 // 图片分类Tabs区块
1036 .img-tabs-block { 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 .img-tab-content { 1056 .img-tab-content {
1040 padding: 20rpx 15px ; 1057 padding: 20rpx 15px ;
@@ -1046,7 +1063,7 @@ onShow(() =&gt; {}); @@ -1046,7 +1063,7 @@ onShow(() =&gt; {});
1046 .empty-img-text { 1063 .empty-img-text {
1047 height: 75px; 1064 height: 75px;
1048 line-height: 75px; 1065 line-height: 75px;
1049 - color: #999; 1066 + color: #909399;
1050 font-size: 28rpx; 1067 font-size: 28rpx;
1051 } 1068 }
1052 } 1069 }
@@ -1059,9 +1076,11 @@ onShow(() =&gt; {}); @@ -1059,9 +1076,11 @@ onShow(() =&gt; {});
1059 } 1076 }
1060 1077
1061 .vertical-steps { 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 display: flex; 1084 display: flex;
1066 flex-direction: column; 1085 flex-direction: column;
1067 gap: 20rpx; 1086 gap: 20rpx;
@@ -1074,20 +1093,20 @@ onShow(() =&gt; {}); @@ -1074,20 +1093,20 @@ onShow(() =&gt; {});
1074 .step-title { 1093 .step-title {
1075 font-size: 30rpx; 1094 font-size: 30rpx;
1076 font-weight: 600; 1095 font-weight: 600;
1077 - color: #333; 1096 + color: #1a1a1a;
1078 margin-bottom: 12rpx; 1097 margin-bottom: 12rpx;
1079 1098
1080 .operator-name { 1099 .operator-name {
1081 font-size: 30rpx; 1100 font-size: 30rpx;
1082 font-weight: 600; 1101 font-weight: 600;
1083 - color: #333; 1102 + color: #1a1a1a;
1084 margin-left: 20rpx; 1103 margin-left: 20rpx;
1085 } 1104 }
1086 } 1105 }
1087 1106
1088 .step-desc { 1107 .step-desc {
1089 font-size: 24rpx; 1108 font-size: 24rpx;
1090 - color: #666; 1109 + color: #606266;
1091 line-height: 1.6; 1110 line-height: 1.6;
1092 margin-bottom: 12rpx; 1111 margin-bottom: 12rpx;
1093 1112
@@ -1111,7 +1130,7 @@ onShow(() =&gt; {}); @@ -1111,7 +1130,7 @@ onShow(() =&gt; {});
1111 1130
1112 .no-img-tip { 1131 .no-img-tip {
1113 font-size: 24rpx; 1132 font-size: 24rpx;
1114 - color: #999; 1133 + color: #909399;
1115 margin-top: 10rpx; 1134 margin-top: 10rpx;
1116 } 1135 }
1117 } 1136 }
@@ -1124,7 +1143,7 @@ onShow(() =&gt; {}); @@ -1124,7 +1143,7 @@ onShow(() =&gt; {});
1124 1143
1125 .upload-title { 1144 .upload-title {
1126 font-size: 28rpx; 1145 font-size: 28rpx;
1127 - color: #333; 1146 + color: #1a1a1a;
1128 margin-bottom: 10rpx; 1147 margin-bottom: 10rpx;
1129 } 1148 }
1130 } 1149 }
@@ -1173,7 +1192,7 @@ onShow(() =&gt; {}); @@ -1173,7 +1192,7 @@ onShow(() =&gt; {});
1173 } 1192 }
1174 1193
1175 // 底部动作按钮:动作多时自动换行 1194 // 底部动作按钮:动作多时自动换行
1176 -// 底部操作栏:白底 + 顶部投影,按钮每行最多 3 个,避免多动作时整屏遮挡工单详情 1195 +// 底部操作栏:白底 + 顶部投影,按钮每行最多 5 个,避免多动作时整屏遮挡工单详情
1177 .order-action-bar { 1196 .order-action-bar {
1178 background-color: #fff; 1197 background-color: #fff;
1179 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06); 1198 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
@@ -1183,20 +1202,19 @@ onShow(() =&gt; {}); @@ -1183,20 +1202,19 @@ onShow(() =&gt; {});
1183 } 1202 }
1184 1203
1185 .order-action-row { 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 .order-action-btn { 1211 .order-action-btn {
1192 box-sizing: border-box; 1212 box-sizing: border-box;
1193 - width: calc((100% - 36rpx) / 3);  
1194 height: 68rpx; 1213 height: 68rpx;
1195 line-height: 68rpx; 1214 line-height: 68rpx;
1196 - margin: 6rpx;  
1197 padding: 0 8rpx; 1215 padding: 0 8rpx;
1198 border-radius: 8rpx; 1216 border-radius: 8rpx;
1199 - font-size: 26rpx; 1217 + font-size: 28rpx;
1200 text-align: center; 1218 text-align: center;
1201 color: #fff; 1219 color: #fff;
1202 white-space: nowrap; 1220 white-space: nowrap;
@@ -1204,17 +1222,21 @@ onShow(() =&gt; {}); @@ -1204,17 +1222,21 @@ onShow(() =&gt; {});
1204 text-overflow: ellipsis; 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 .order-action-btn--success { 1238 .order-action-btn--success {
1217 - background-color: #5ac725; 1239 + background-color: #078d0a;
1218 } 1240 }
1219 1241
1220 .order-action-btn--warning { 1242 .order-action-btn--warning {
pages-sub/problem/work-order-manage/add-maintain-order.vue
1 <template> 1 <template>
2 <view class="page-container"> 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 <view class="work-order-form-content commonPageLRpadding"> 8 <view class="work-order-form-content commonPageLRpadding">
4 <up-form 9 <up-form
5 label-position="left" 10 label-position="left"
@@ -7,6 +12,12 @@ @@ -7,6 +12,12 @@
7 ref="workOrderFormRef" 12 ref="workOrderFormRef"
8 labelWidth="170rpx" 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 <!-- 1. 工单编号(只读展示,从缓存获取) --> 21 <!-- 1. 工单编号(只读展示,从缓存获取) -->
11 <up-form-item 22 <up-form-item
12 label="工单编号" 23 label="工单编号"
@@ -59,7 +70,14 @@ @@ -59,7 +70,14 @@
59 </template> 70 </template>
60 </up-form-item> 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 <up-form-item 81 <up-form-item
64 label="处理情况" 82 label="处理情况"
65 prop="reason" 83 prop="reason"
@@ -74,10 +92,14 @@ @@ -74,10 +92,14 @@
74 @blur="() => workOrderFormRef.validateField('reason')" 92 @blur="() => workOrderFormRef.validateField('reason')"
75 ></up-textarea> 93 ></up-textarea>
76 </up-form-item> 94 </up-form-item>
  95 + </view>
77 96
78 <!-- 4. 动态字段:按「业务类型(busiLine) + 作业类型」加载数据中心配置的工单填报项 --> 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 <work-field-form 103 <work-field-form
82 ref="workFieldFormRef" 104 ref="workFieldFormRef"
83 :business-type="workOrderForm.businessType" 105 :business-type="workOrderForm.businessType"
@@ -90,13 +112,19 @@ @@ -90,13 +112,19 @@
90 </view> 112 </view>
91 </view> 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 <!-- Tabs标签栏(图片切换:开始、进行中、结束、人员、材料)- 改造后 --> 121 <!-- Tabs标签栏(图片切换:开始、进行中、结束、人员、材料)- 改造后 -->
94 - <view class="tabs-wrap " style="margin-top: 30rpx;"> 122 + <view class="tabs-wrap">
95 <up-tabs 123 <up-tabs
96 v-model="activeTab" 124 v-model="activeTab"
97 :list="tabList" 125 :list="tabList"
98 line-width="40rpx" 126 line-width="40rpx"
99 - active-color="#1989fa" 127 + active-color="#2563EB"
100 inactive-color="#666666" 128 inactive-color="#666666"
101 @change = "imgTabChange" 129 @change = "imgTabChange"
102 130
@@ -110,7 +138,7 @@ @@ -110,7 +138,7 @@
110 </view> 138 </view>
111 </template> 139 </template>
112 </up-tabs> 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 <view v-if="activeTab == 0"> 143 <view v-if="activeTab == 0">
116 <up-form-item prop="startImgs"> 144 <up-form-item prop="startImgs">
@@ -183,6 +211,7 @@ @@ -183,6 +211,7 @@
183 </view> 211 </view>
184 </view> 212 </view>
185 </view> 213 </view>
  214 + </view>
186 </up-form> 215 </up-form>
187 </view> 216 </view>
188 217
@@ -1022,16 +1051,94 @@ const submitWorkOrder = async () =&gt; { @@ -1022,16 +1051,94 @@ const submitWorkOrder = async () =&gt; {
1022 </script> 1051 </script>
1023 1052
1024 <style lang="scss" scoped> 1053 <style lang="scss" scoped>
1025 -// 页面容器样式 1054 +// 页面容器:浅灰底 + 给底部固定栏(按钮 88rpx + 上下各 24rpx)留空间
1026 .page-container { 1055 .page-container {
1027 min-height: 100vh; 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 .work-order-form-content { 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 // Tabs容器样式 1144 // Tabs容器样式
@@ -1051,23 +1158,39 @@ const submitWorkOrder = async () =&gt; { @@ -1051,23 +1158,39 @@ const submitWorkOrder = async () =&gt; {
1051 font-weight: bold; 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 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 - <view class="work-order-form-content commonPageLRpadding"> 3 + <view class="work-order-form-content">
4 <up-form label-position="left" :model="workOrderForm" ref="workOrderFormRef" labelWidth="200rpx"> 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 </up-form> 107 </up-form>
79 </view> 108 </view>
80 <!-- 底部提交按钮 --> 109 <!-- 底部提交按钮 -->
81 <view class="fixed-bottom-btn-wrap"> 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 </view> 112 </view>
84 <!-- 通用下拉弹窗:道路名称、紧急程度保留 --> 113 <!-- 通用下拉弹窗:道路名称、紧急程度保留 -->
85 <up-action-sheet :show="showActionSheet" :actions="currentActionSheetData.list" 114 <up-action-sheet :show="showActionSheet" :actions="currentActionSheetData.list"
@@ -586,9 +615,104 @@ const submitWorkOrder = async () =&gt; { @@ -586,9 +615,104 @@ const submitWorkOrder = async () =&gt; {
586 <style lang="scss" scoped> 615 <style lang="scss" scoped>
587 .page-container { 616 .page-container {
588 min-height: 100vh; 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 .work-order-form-content { 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 </style> 718 </style>
pages-sub/problem/work-order-manage/distribution-order.vue
@@ -7,52 +7,66 @@ @@ -7,52 +7,66 @@
7 ref="workOrderFormRef" 7 ref="workOrderFormRef"
8 labelWidth="190rpx" 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 </up-form> 70 </up-form>
57 </view> 71 </view>
58 72
@@ -60,7 +74,7 @@ @@ -60,7 +74,7 @@
60 <view class="fixed-bottom-btn-wrap"> 74 <view class="fixed-bottom-btn-wrap">
61 <up-button 75 <up-button
62 type="primary" 76 type="primary"
63 - text="提交" 77 + text="确认分配"
64 @click="submitWorkOrder" 78 @click="submitWorkOrder"
65 ></up-button> 79 ></up-button>
66 </view> 80 </view>
@@ -279,15 +293,106 @@ const submitWorkOrder = async () =&gt; { @@ -279,15 +293,106 @@ const submitWorkOrder = async () =&gt; {
279 </script> 293 </script>
280 294
281 <style lang="scss" scoped> 295 <style lang="scss" scoped>
282 -// 全局页面样式 296 +// 页面容器:浅灰底 + 给底部固定栏(按钮 88rpx + 上下各 24rpx)留空间
283 .page-container { 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 .work-order-form-content { 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,8 +7,8 @@
7 <up-tabs 7 <up-tabs
8 v-model="activeTab" 8 v-model="activeTab"
9 :list="tabList" 9 :list="tabList"
10 - active-color="#1989fa"  
11 - inactive-color="#666" 10 + active-color="#2563EB"
  11 + inactive-color="#606266"
12 font-size="30rpx" 12 font-size="30rpx"
13 @click="handleTabChange" 13 @click="handleTabChange"
14 /> 14 />
@@ -57,7 +57,7 @@ @@ -57,7 +57,7 @@
57 <empty-view/> 57 <empty-view/>
58 </template> 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 <up-card 62 <up-card
63 v-if="activeTab == 0" 63 v-if="activeTab == 0"
@@ -70,6 +70,8 @@ @@ -70,6 +70,8 @@
70 > 70 >
71 <template #body> 71 <template #body>
72 <view class="card-body"> 72 <view class="card-body">
  73 + <!-- 卡片标题:工单名称(设计稿 .card-title) -->
  74 + <view class="card-title u-line-1">{{ item.orderName || '未填写' }}</view>
73 <view class="u-body-item u-flex"> 75 <view class="u-body-item u-flex">
74 <view class="u-body-item-title">工单编号:</view> 76 <view class="u-body-item-title">工单编号:</view>
75 <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view> 77 <view class="u-line-1 u-body-value">{{ item.orderNo || '-' }}</view>
@@ -79,10 +81,6 @@ @@ -79,10 +81,6 @@
79 <view class="u-line-1 u-body-value">{{ item.lonLatAddress || '-' }}</view> 81 <view class="u-line-1 u-body-value">{{ item.lonLatAddress || '-' }}</view>
80 </view> 82 </view>
81 <view class="u-body-item u-flex"> 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 <view class="u-body-item-title">情况描述:</view> 84 <view class="u-body-item-title">情况描述:</view>
87 <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view> 85 <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view>
88 </view> 86 </view>
@@ -101,16 +99,17 @@ @@ -101,16 +99,17 @@
101 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view> 99 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
102 </view> 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 <template v-if="hasConfiguredActions(item)"> 105 <template v-if="hasConfiguredActions(item)">
107 <view 106 <view
108 v-for="action in item.configuredActions" 107 v-for="action in item.configuredActions"
109 :key="action.code" 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 @click.stop="handleUnifiedProcess(item, action)" 110 @click.stop="handleUnifiedProcess(item, action)"
112 >{{ action.name }}</view> 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 </template> 113 </template>
115 <!-- 未配置:沿用原有节点按钮 --> 114 <!-- 未配置:沿用原有节点按钮 -->
116 <template v-else> 115 <template v-else>
@@ -120,7 +119,7 @@ @@ -120,7 +119,7 @@
120 @click.stop="handleRenew(item)">重新提交</view> 119 @click.stop="handleRenew(item)">重新提交</view>
121 <view class="task-btn task-btn--primary" 120 <view class="task-btn task-btn--primary"
122 @click.stop="handleUnifiedProcess(item)">{{ getProcessButtonText(item) }}</view> 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 </template> 123 </template>
125 </view> 124 </view>
126 </view> 125 </view>
@@ -139,13 +138,8 @@ @@ -139,13 +138,8 @@
139 > 138 >
140 <template #body> 139 <template #body>
141 <view class="card-body"> 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 <view class="u-body-item u-flex"> 144 <view class="u-body-item u-flex">
151 <view class="u-body-item-title">工单编号:</view> 145 <view class="u-body-item-title">工单编号:</view>
@@ -156,20 +150,13 @@ @@ -156,20 +150,13 @@
156 <view class="u-line-1 u-body-value">{{ item.lonLatAddress || '-' }}</view> 150 <view class="u-line-1 u-body-value">{{ item.lonLatAddress || '-' }}</view>
157 </view> 151 </view>
158 <view class="u-body-item u-flex"> 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 <view class="u-body-item-title">情况描述:</view> 153 <view class="u-body-item-title">情况描述:</view>
164 <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view> 154 <view class="u-line-1 u-body-value">{{ item.remark || '无' }}</view>
165 </view> 155 </view>
166 156
167 <view class="u-body-item u-flex common-justify-between common-item-center"> 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 </view> 160 </view>
174 <view class="u-body-item u-flex"> 161 <view class="u-body-item u-flex">
175 <view class="u-body-item-title">工单状态:</view> 162 <view class="u-body-item-title">工单状态:</view>
@@ -179,6 +166,11 @@ @@ -179,6 +166,11 @@
179 <view class="u-body-item-title">提交时间:</view> 166 <view class="u-body-item-title">提交时间:</view>
180 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view> 167 <view class="u-line-1 u-body-value">{{ timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
181 </view> 168 </view>
  169 +
  170 + <!-- 底部操作:分隔线 + 查看详情(设计稿 .card-foot) -->
  171 + <view class="card-foot">
  172 + <view class="foot-btn" @click="handleDetail(item)">工单详情</view>
  173 + </view>
182 </view> 174 </view>
183 </template> 175 </template>
184 </up-card> 176 </up-card>
@@ -298,7 +290,7 @@ import { @@ -298,7 +290,7 @@ import {
298 } from '@/api/work-order-manage/work-order-manage' 290 } from '@/api/work-order-manage/work-order-manage'
299 // 从用户store获取角色信息 291 // 从用户store获取角色信息
300 import { useUserStore } from '@/pinia/user'; 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 import { useUploadImgs } from '@/common/utils/useUploadImgs' 295 import { useUploadImgs } from '@/common/utils/useUploadImgs'
304 296
@@ -346,7 +338,6 @@ const rejectImgs = useUploadImgs({ @@ -346,7 +338,6 @@ const rejectImgs = useUploadImgs({
346 fieldName: 'rejectImgs' // 自定义字段名 338 fieldName: 'rejectImgs' // 自定义字段名
347 }) 339 })
348 340
349 -  
350 // ========== 验收弹窗相关状态(含图片上传) ========== 341 // ========== 验收弹窗相关状态(含图片上传) ==========
351 const acceptModalShow = ref(false); // 验收弹窗显示开关 342 const acceptModalShow = ref(false); // 验收弹窗显示开关
352 const acceptRadioValue = ref('0'); // 单选框值,默认0(通过) 343 const acceptRadioValue = ref('0'); // 单选框值,默认0(通过)
@@ -389,7 +380,6 @@ const openMapNav = (item) =&gt; { @@ -389,7 +380,6 @@ const openMapNav = (item) =&gt; {
389 // }); 380 // });
390 }; 381 };
391 382
392 -  
393 // 分页查询列表 383 // 分页查询列表
394 const queryList = async (pageNo, pageSize) => { 384 const queryList = async (pageNo, pageSize) => {
395 try { 385 try {
@@ -550,6 +540,17 @@ const getProcessButtonText = (item) =&gt; { @@ -550,6 +540,17 @@ const getProcessButtonText = (item) =&gt; {
550 const hasConfiguredActions = (item) => 540 const hasConfiguredActions = (item) =>
551 Array.isArray(item?.configuredActions) && item.configuredActions.length > 0 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 const handleUnifiedProcess = async (item, action = null) => { 555 const handleUnifiedProcess = async (item, action = null) => {
555 const actions = Array.isArray(item?.configuredActions) 556 const actions = Array.isArray(item?.configuredActions)
@@ -818,7 +819,7 @@ onUnload(() =&gt; { @@ -818,7 +819,7 @@ onUnload(() =&gt; {
818 <style scoped lang="scss"> 819 <style scoped lang="scss">
819 .page-container { 820 .page-container {
820 min-height: 100vh; 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,39 +853,107 @@ onUnload(() =&gt; {
852 } 853 }
853 } 854 }
854 855
855 -// 工单卡片样式 856 +// 工单卡片样式:白底 / 16rpx 圆角 / 卡片阴影(设计稿 .card)
856 .order-card { 857 .order-card {
857 - margin: 0 20rpx 20rpx; 858 + margin: 0 24rpx 24rpx;
858 background: #fff; 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 .task-btn-row { 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 display: flex; 901 display: flex;
865 - flex-wrap: wrap;  
866 justify-content: flex-end; 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 .task-btn { 928 .task-btn {
871 box-sizing: border-box; 929 box-sizing: border-box;
872 height: 56rpx; 930 height: 56rpx;
873 line-height: 56rpx; 931 line-height: 56rpx;
874 - padding: 0 24rpx;  
875 - margin: 0 0 10rpx 12rpx; 932 + padding: 0 12rpx;
876 border-radius: 8rpx; 933 border-radius: 8rpx;
877 font-size: 24rpx; 934 font-size: 24rpx;
878 color: #fff; 935 color: #fff;
  936 + text-align: center;
879 white-space: nowrap; 937 white-space: nowrap;
  938 + overflow: hidden;
  939 + text-overflow: ellipsis;
880 } 940 }
881 941
  942 +/* 按动作编码配色:通过/实施/结束类动作绿色,退回类橙色 */
882 .task-btn--primary { 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 .task-btn--success { 955 .task-btn--success {
887 - background-color: #5ac725; 956 + background-color: #078d0a;
888 } 957 }
889 958
890 .task-btn--warning { 959 .task-btn--warning {
@@ -899,8 +968,6 @@ onUnload(() =&gt; { @@ -899,8 +968,6 @@ onUnload(() =&gt; {
899 background-color: #909399; 968 background-color: #909399;
900 } 969 }
901 970
902 -  
903 -  
904 // 回退modal样式 971 // 回退modal样式
905 .reject-modal-content { 972 .reject-modal-content {
906 width: 100%; 973 width: 100%;
@@ -910,7 +977,7 @@ onUnload(() =&gt; { @@ -910,7 +977,7 @@ onUnload(() =&gt; {
910 977
911 .textarea-label { 978 .textarea-label {
912 font-size: 28rpx; 979 font-size: 28rpx;
913 - color: #333; 980 + color: #1a1a1a;
914 margin-bottom: 10rpx; 981 margin-bottom: 10rpx;
915 982
916 .required-mark { 983 .required-mark {
@@ -924,7 +991,7 @@ onUnload(() =&gt; { @@ -924,7 +991,7 @@ onUnload(() =&gt; {
924 991
925 .upload-title { 992 .upload-title {
926 font-size: 28rpx; 993 font-size: 28rpx;
927 - color: #333; 994 + color: #1a1a1a;
928 margin-bottom: 10rpx; 995 margin-bottom: 10rpx;
929 } 996 }
930 } 997 }
pages-sub/problem/work-order-manage/order-detail.vue
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 v-if="loading" 5 v-if="loading"
6 :loading="true" 6 :loading="true"
7 title="加载中..." 7 title="加载中..."
8 - color="#3c9cff" 8 + color="#2563EB"
9 ></up-loading-page> 9 ></up-loading-page>
10 10
11 <!-- 主内容容器 --> 11 <!-- 主内容容器 -->
@@ -17,8 +17,8 @@ @@ -17,8 +17,8 @@
17 :list="topTabList" 17 :list="topTabList"
18 :scrollable="false" 18 :scrollable="false"
19 sticky 19 sticky
20 - active-color="#3c9cff"  
21 - inactive-color="#666" 20 + active-color="#2563EB"
  21 + inactive-color="#606266"
22 class="top-tabs" 22 class="top-tabs"
23 @click="activeTopTabClick" 23 @click="activeTopTabClick"
24 ></up-tabs> 24 ></up-tabs>
@@ -29,6 +29,11 @@ @@ -29,6 +29,11 @@
29 <!-- 1. 工单详情Tab --> 29 <!-- 1. 工单详情Tab -->
30 <view v-show="activeTopTab == 0" class="detail-content"> 30 <view v-show="activeTopTab == 0" class="detail-content">
31 <up-cell-group :border="false" class="detail-cell-group"> 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 <up-cell title="工单编号" :value="orderDetail.orderNo || '--'" align="middle"></up-cell> 38 <up-cell title="工单编号" :value="orderDetail.orderNo || '--'" align="middle"></up-cell>
34 39
@@ -63,16 +68,6 @@ @@ -63,16 +68,6 @@
63 </template> 68 </template>
64 </up-cell> 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 <up-cell 72 <up-cell
78 title="紧急程度" 73 title="紧急程度"
@@ -100,24 +95,6 @@ @@ -100,24 +95,6 @@
100 </template> 95 </template>
101 </up-cell> 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 <up-cell title="重点巡检区域" :value="orderDetail.keyInspection==0?'否':'是'" align="middle"></up-cell> 98 <up-cell title="重点巡检区域" :value="orderDetail.keyInspection==0?'否':'是'" align="middle"></up-cell>
122 99
123 <!-- 希望完成时间 --> 100 <!-- 希望完成时间 -->
@@ -138,6 +115,41 @@ @@ -138,6 +115,41 @@
138 ></up-cell> 115 ></up-cell>
139 </up-cell-group> 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 <!-- 图片分类Tabs区块 --> 153 <!-- 图片分类Tabs区块 -->
142 <view class="img-tabs-block" v-if="orderDetail.startImgs.length>0"> 154 <view class="img-tabs-block" v-if="orderDetail.startImgs.length>0">
143 <up-cell-group :border="false"> 155 <up-cell-group :border="false">
@@ -159,8 +171,8 @@ @@ -159,8 +171,8 @@
159 v-model="activeImgTab" 171 v-model="activeImgTab"
160 :list="imgTabList" 172 :list="imgTabList"
161 :scrollable="false" 173 :scrollable="false"
162 - active-color="#3c9cff"  
163 - inactive-color="#666" 174 + active-color="#2563EB"
  175 + inactive-color="#606266"
164 class="img-tabs" 176 class="img-tabs"
165 ></up-tabs> 177 ></up-tabs>
166 178
@@ -180,7 +192,10 @@ @@ -180,7 +192,10 @@
180 192
181 <!-- 作业填报明细(工单实施时按「业务类型+作业类型」动态字段配置填报) --> 193 <!-- 作业填报明细(工单实施时按「业务类型+作业类型」动态字段配置填报) -->
182 <view class="work-field-block" v-if="workFieldValues.length > 0"> 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 <up-cell-group :border="false"> 199 <up-cell-group :border="false">
185 <up-cell 200 <up-cell
186 v-for="item in workFieldValues" 201 v-for="item in workFieldValues"
@@ -223,8 +238,8 @@ @@ -223,8 +238,8 @@
223 :list="processData.activityNodes" 238 :list="processData.activityNodes"
224 :current="getCurrentStepIndex()" 239 :current="getCurrentStepIndex()"
225 direction="column" 240 direction="column"
226 - active-color="#3c9cff"  
227 - inactive-color="#999" 241 + active-color="#2563EB"
  242 + inactive-color="#909399"
228 class="vertical-steps" 243 class="vertical-steps"
229 > 244 >
230 <template> 245 <template>
@@ -237,7 +252,7 @@ @@ -237,7 +252,7 @@
237 <view class="step-content-wrap"> 252 <view class="step-content-wrap">
238 <!-- 1. 原标题内容:节点名称 + 操作人 --> 253 <!-- 1. 原标题内容:节点名称 + 操作人 -->
239 <view class="step-title"> 254 <view class="step-title">
240 - {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }} 255 + {{ item.name }}
241 </view> 256 </view>
242 257
243 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) --> 258 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) -->
@@ -294,17 +309,18 @@ @@ -294,17 +309,18 @@
294 <!-- activeTab==0的时候才出现, 也就是待办 --> 309 <!-- activeTab==0的时候才出现, 也就是待办 -->
295 <view v-if="activeTab==0&&(configuredActions||nextStepMap[orderDetail.taskKey])" 310 <view v-if="activeTab==0&&(configuredActions||nextStepMap[orderDetail.taskKey])"
296 class="fixed-bottom-btn-wrap order-action-bar"> 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 <view 315 <view
300 v-for="action in configuredActions" 316 v-for="action in configuredActions"
301 :key="action.code" 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 @click.stop="handleUnifiedProcess(orderDetail, action)" 319 @click.stop="handleUnifiedProcess(orderDetail, action)"
304 >{{ action.name }}</view> 320 >{{ action.name }}</view>
305 </view> 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 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning" 324 <view v-if="showRejectButton" class="order-action-btn order-action-btn--warning"
309 @click.stop="handleUnifiedReject(orderDetail)">回退</view> 325 @click.stop="handleUnifiedReject(orderDetail)">回退</view>
310 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success" 326 <view v-if="nextStepMap[orderDetail.taskKey]?.renewShow" class="order-action-btn order-action-btn--success"
@@ -418,7 +434,7 @@ import { @@ -418,7 +434,7 @@ import {
418 getTaskActions 434 getTaskActions
419 } from '@/api/work-order-manage/work-order-manage'; 435 } from '@/api/work-order-manage/work-order-manage';
420 import {getWorkRecordValues} from '@/api/common' 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 import {useUploadImgs} from '@/common/utils/useUploadImgs' 439 import {useUploadImgs} from '@/common/utils/useUploadImgs'
424 440
@@ -813,15 +829,20 @@ const showRejectButton = computed(() =&gt; { @@ -813,15 +829,20 @@ const showRejectButton = computed(() =&gt; {
813 const hasConfiguredActions = computed(() => 829 const hasConfiguredActions = computed(() =>
814 Array.isArray(configuredActions.value) && configuredActions.value.length > 0) 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 const actionBarRows = computed(() => { 841 const actionBarRows = computed(() => {
818 if (hasConfiguredActions.value) { 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,6 +1086,7 @@ onShow(() =&gt; {
1065 // 全局样式 1086 // 全局样式
1066 .page-container { 1087 .page-container {
1067 min-height: 100vh; 1088 min-height: 100vh;
  1089 + background-color: #F4F6FA;
1068 } 1090 }
1069 1091
1070 // 主内容容器 1092 // 主内容容器
@@ -1072,6 +1094,27 @@ onShow(() =&gt; { @@ -1072,6 +1094,27 @@ onShow(() =&gt; {
1072 padding-bottom: 80rpx; 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 // 顶部Tabs 1118 // 顶部Tabs
1076 .top-tabs { 1119 .top-tabs {
1077 //background-color: #fff; 1120 //background-color: #fff;
@@ -1084,45 +1127,68 @@ onShow(() =&gt; { @@ -1084,45 +1127,68 @@ onShow(() =&gt; {
1084 1127
1085 // 工单详情内容 1128 // 工单详情内容
1086 .detail-content { 1129 .detail-content {
  1130 + // 白色卡片:16rpx 圆角 + 卡片阴影(设计稿 .card)
1087 .detail-cell-group { 1131 .detail-cell-group {
1088 background-color: #fff; 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 .cell-content-wrap { 1144 .cell-content-wrap {
1093 // 保持原有样式,兼容up-album布局 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 .empty-text { 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 .img-tabs-block { 1165 .img-tabs-block {
  1166 + margin: 0 24rpx 24rpx;
1104 background-color: #fff; 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 .img-tab-content { 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 .empty-img-text { 1188 .empty-img-text {
1123 height: 75px; 1189 height: 75px;
1124 line-height: 75px; 1190 line-height: 75px;
1125 - color: #999; 1191 + color: #9CA3AF;
1126 font-size: 28rpx; 1192 font-size: 28rpx;
1127 } 1193 }
1128 } 1194 }
@@ -1137,12 +1203,14 @@ onShow(() =&gt; { @@ -1137,12 +1203,14 @@ onShow(() =&gt; {
1137 margin-top: 100rpx; 1203 margin-top: 100rpx;
1138 } 1204 }
1139 1205
1140 - // 竖向步骤条容器样式 1206 + // 竖向步骤条容器样式:白色卡片(设计稿 .card)
1141 .vertical-steps { 1207 .vertical-steps {
1142 //width: 100%; 1208 //width: 100%;
  1209 + margin: 24rpx 24rpx 0;
1143 background-color: #fff; 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 display: flex; 1214 display: flex;
1147 flex-direction: column; 1215 flex-direction: column;
1148 gap: 20rpx; // 步骤项间距 1216 gap: 20rpx; // 步骤项间距
@@ -1158,13 +1226,13 @@ onShow(() =&gt; { @@ -1158,13 +1226,13 @@ onShow(() =&gt; {
1158 .step-title { 1226 .step-title {
1159 font-size: 30rpx; 1227 font-size: 30rpx;
1160 font-weight: 600; 1228 font-weight: 600;
1161 - color: #333; 1229 + color: #1a1a1a;
1162 margin-bottom: 12rpx; 1230 margin-bottom: 12rpx;
1163 1231
1164 .operator-name { 1232 .operator-name {
1165 font-size: 30rpx; 1233 font-size: 30rpx;
1166 font-weight: 600; 1234 font-weight: 600;
1167 - color: #333; 1235 + color: #1a1a1a;
1168 margin-left: 20rpx; 1236 margin-left: 20rpx;
1169 } 1237 }
1170 } 1238 }
@@ -1172,7 +1240,7 @@ onShow(() =&gt; { @@ -1172,7 +1240,7 @@ onShow(() =&gt; {
1172 // 描述(时间 + 处理说明)样式 1240 // 描述(时间 + 处理说明)样式
1173 .step-desc { 1241 .step-desc {
1174 font-size: 24rpx; 1242 font-size: 24rpx;
1175 - color: #666; 1243 + color: #606266;
1176 line-height: 1.6; 1244 line-height: 1.6;
1177 margin-bottom: 12rpx; 1245 margin-bottom: 12rpx;
1178 1246
@@ -1199,7 +1267,7 @@ onShow(() =&gt; { @@ -1199,7 +1267,7 @@ onShow(() =&gt; {
1199 1267
1200 .no-img-tip { 1268 .no-img-tip {
1201 font-size: 24rpx; 1269 font-size: 24rpx;
1202 - color: #999; 1270 + color: #909399;
1203 margin-top: 10rpx; 1271 margin-top: 10rpx;
1204 } 1272 }
1205 } 1273 }
@@ -1212,7 +1280,7 @@ onShow(() =&gt; { @@ -1212,7 +1280,7 @@ onShow(() =&gt; {
1212 1280
1213 .upload-title { 1281 .upload-title {
1214 font-size: 28rpx; 1282 font-size: 28rpx;
1215 - color: #333; 1283 + color: #1a1a1a;
1216 margin-bottom: 10rpx; 1284 margin-bottom: 10rpx;
1217 } 1285 }
1218 } 1286 }
@@ -1261,7 +1329,7 @@ onShow(() =&gt; { @@ -1261,7 +1329,7 @@ onShow(() =&gt; {
1261 } 1329 }
1262 1330
1263 // 底部动作按钮:动作多时自动换行 1331 // 底部动作按钮:动作多时自动换行
1264 -// 底部操作栏:白底 + 顶部投影,按钮每行最多 3 个,避免多动作时整屏遮挡工单详情 1332 +// 底部操作栏:白底 + 顶部投影,按钮每行最多 5 个,避免多动作时整屏遮挡工单详情
1265 .order-action-bar { 1333 .order-action-bar {
1266 background-color: #fff; 1334 background-color: #fff;
1267 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06); 1335 box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
@@ -1271,20 +1339,19 @@ onShow(() =&gt; { @@ -1271,20 +1339,19 @@ onShow(() =&gt; {
1271 } 1339 }
1272 1340
1273 .order-action-row { 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 .order-action-btn { 1348 .order-action-btn {
1280 box-sizing: border-box; 1349 box-sizing: border-box;
1281 - width: calc((100% - 36rpx) / 3);  
1282 height: 68rpx; 1350 height: 68rpx;
1283 line-height: 68rpx; 1351 line-height: 68rpx;
1284 - margin: 6rpx;  
1285 padding: 0 8rpx; 1352 padding: 0 8rpx;
1286 border-radius: 8rpx; 1353 border-radius: 8rpx;
1287 - font-size: 26rpx; 1354 + font-size: 28rpx;
1288 text-align: center; 1355 text-align: center;
1289 color: #fff; 1356 color: #fff;
1290 white-space: nowrap; 1357 white-space: nowrap;
@@ -1292,17 +1359,21 @@ onShow(() =&gt; { @@ -1292,17 +1359,21 @@ onShow(() =&gt; {
1292 text-overflow: ellipsis; 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 .order-action-btn--success { 1375 .order-action-btn--success {
1305 - background-color: #5ac725; 1376 + background-color: #078d0a;
1306 } 1377 }
1307 1378
1308 .order-action-btn--warning { 1379 .order-action-btn--warning {
@@ -1330,16 +1401,23 @@ onShow(() =&gt; { @@ -1330,16 +1401,23 @@ onShow(() =&gt; {
1330 padding-bottom: 390rpx; 1401 padding-bottom: 390rpx;
1331 } 1402 }
1332 1403
1333 -// 作业填报明细 1404 +// 作业填报明细:白色卡片(设计稿 .card)
1334 .work-field-block { 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 .work-field-value { 1423 .work-field-value {
@@ -1359,8 +1437,8 @@ onShow(() =&gt; { @@ -1359,8 +1437,8 @@ onShow(() =&gt; {
1359 1437
1360 .work-field-file { 1438 .work-field-file {
1361 max-width: 420rpx; 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,9 +310,9 @@
310 } 310 }
311 }, 311 },
312 "globalStyle": { 312 "globalStyle": {
313 - "navigationBarTextStyle": "black", 313 + "navigationBarTextStyle": "white",
314 "navigationBarTitleText": "JCSS管理系统", 314 "navigationBarTitleText": "JCSS管理系统",
315 - "navigationBarBackgroundColor": "#ffffff", 315 + "navigationBarBackgroundColor": "#2563EB",
316 "backgroundColor": "#f8f8f8" 316 "backgroundColor": "#f8f8f8"
317 } 317 }
318 } 318 }
319 \ No newline at end of file 319 \ No newline at end of file
pages/index/index.vue
@@ -46,7 +46,7 @@ @@ -46,7 +46,7 @@
46 <up-grid :border="false" col="4"> 46 <up-grid :border="false" col="4">
47 <up-grid-item v-for="(baseListItem, baseListIndex) in baseList" :key="baseListIndex"> 47 <up-grid-item v-for="(baseListItem, baseListIndex) in baseList" :key="baseListIndex">
48 <view class="grid-item-icon-box"> 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 <text class="grid-num-icon">{{ baseListItem.num }}</text> 50 <text class="grid-num-icon">{{ baseListItem.num }}</text>
51 <text class="grid-label-icon">{{ baseListItem.title }}</text> 51 <text class="grid-label-icon">{{ baseListItem.title }}</text>
52 </view> 52 </view>
@@ -87,7 +87,7 @@ @@ -87,7 +87,7 @@
87 <!-- 顶部进度提示栏 --> 87 <!-- 顶部进度提示栏 -->
88 <view v-if="showTipHeader" class="tip-header"> 88 <view v-if="showTipHeader" class="tip-header">
89 <up-icon name="checkmark-circle" color="#00b42a" size="20"></up-icon> 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 </view> 91 </view>
92 <scroll-view class="task-list-container" scroll-y @scroll="onListScroll" @scrolltoupper="handleTouchTop" enhanced> 92 <scroll-view class="task-list-container" scroll-y @scroll="onListScroll" @scrolltoupper="handleTouchTop" enhanced>
93 <view v-if="taskList.length === 0" class="empty-box"> 93 <view v-if="taskList.length === 0" class="empty-box">
@@ -635,9 +635,9 @@ onUnload(() =&gt; { @@ -635,9 +635,9 @@ onUnload(() =&gt; {
635 </script> 635 </script>
636 636
637 <style scoped lang="scss"> 637 <style scoped lang="scss">
638 -$primary-color: #1677ff; 638 +$primary-color: #2563EB;
639 $danger-color: #E53935; 639 $danger-color: #E53935;
640 -$text-color: #333; 640 +$text-color: #1a1a1a;
641 $text-color-light: #666; 641 $text-color-light: #666;
642 $text-placeholder: #999; 642 $text-placeholder: #999;
643 $bg-color: #f5f5f7; 643 $bg-color: #f5f5f7;
@@ -665,7 +665,7 @@ $border-color: #e5e5e5; @@ -665,7 +665,7 @@ $border-color: #e5e5e5;
665 align-items: center; 665 align-items: center;
666 color: #fff; 666 color: #fff;
667 .username { 667 .username {
668 - font-size: 32rpx; 668 + font-size: 30rpx;
669 margin-bottom: 4rpx; 669 margin-bottom: 4rpx;
670 } 670 }
671 .login-desc { 671 .login-desc {
@@ -764,11 +764,11 @@ $border-color: #e5e5e5; @@ -764,11 +764,11 @@ $border-color: #e5e5e5;
764 .main-tab-item { 764 .main-tab-item {
765 padding: 24rpx 16rpx; 765 padding: 24rpx 16rpx;
766 font-size: 30rpx; 766 font-size: 30rpx;
767 - color: #666; 767 + color: #606266;
768 position: relative; 768 position: relative;
769 transition: color 0.24s; 769 transition: color 0.24s;
770 &.active { 770 &.active {
771 - color: #1677ff; 771 + color: #2563EB;
772 font-weight: 500; 772 font-weight: 500;
773 &::after { 773 &::after {
774 content: ''; 774 content: '';
@@ -777,7 +777,7 @@ $border-color: #e5e5e5; @@ -777,7 +777,7 @@ $border-color: #e5e5e5;
777 bottom: 0; 777 bottom: 0;
778 width: 100%; 778 width: 100%;
779 height: 4rpx; 779 height: 4rpx;
780 - background-color: #1677ff; 780 + background-color: #2563EB;
781 border-radius: 2rpx; 781 border-radius: 2rpx;
782 } 782 }
783 } 783 }
@@ -794,7 +794,7 @@ $border-color: #e5e5e5; @@ -794,7 +794,7 @@ $border-color: #e5e5e5;
794 .tab-capsule { 794 .tab-capsule {
795 padding: 10rpx 20rpx; 795 padding: 10rpx 20rpx;
796 font-size: 28rpx; 796 font-size: 28rpx;
797 - color: #999; 797 + color: #909399;
798 background: #f5f5f5; 798 background: #f5f5f5;
799 border-radius: 0; 799 border-radius: 0;
800 transition: all 0.2s ease; 800 transition: all 0.2s ease;
@@ -878,7 +878,7 @@ $border-color: #e5e5e5; @@ -878,7 +878,7 @@ $border-color: #e5e5e5;
878 display: flex; 878 display: flex;
879 align-items: flex-start; 879 align-items: flex-start;
880 gap: 6rpx; 880 gap: 6rpx;
881 - font-size: 26rpx; 881 + font-size: 28rpx;
882 color: $text-color-light; 882 color: $text-color-light;
883 margin-top: $spacing-sm; 883 margin-top: $spacing-sm;
884 align-items: center; 884 align-items: center;
@@ -900,12 +900,12 @@ $border-color: #e5e5e5; @@ -900,12 +900,12 @@ $border-color: #e5e5e5;
900 .grid-num-icon { 900 .grid-num-icon {
901 font-size: 40rpx; 901 font-size: 40rpx;
902 font-weight: 600; 902 font-weight: 600;
903 - color: #333; 903 + color: #1a1a1a;
904 margin-top: 8rpx; 904 margin-top: 8rpx;
905 } 905 }
906 .grid-label-icon { 906 .grid-label-icon {
907 - font-size: 22rpx;  
908 - color: #666; 907 + font-size: 24rpx;
  908 + color: #606266;
909 margin-top: 4rpx; 909 margin-top: 4rpx;
910 } 910 }
911 </style> 911 </style>
pages/login/index.vue
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 line-width="55" 14 line-width="55"
15 line-height="2" 15 line-height="2"
16 @change="handleTabChange" 16 @change="handleTabChange"
17 - :activeStyle="{ color: '#3c9cff', fontWeight:'500', fontSize: '14px' }" 17 + :activeStyle="{ color: '#2563EB', fontWeight:'500', fontSize: '14px' }"
18 :inactiveStyle="{ color: '#606060', fontSize: '14px' }" 18 :inactiveStyle="{ color: '#606060', fontSize: '14px' }"
19 ></up-tabs> 19 ></up-tabs>
20 20
@@ -553,7 +553,7 @@ onMounted(() =&gt; { @@ -553,7 +553,7 @@ onMounted(() =&gt; {
553 553
554 :deep(.u-checkbox) { 554 :deep(.u-checkbox) {
555 font-size: 12px; 555 font-size: 12px;
556 - color: #666; 556 + color: #606266;
557 justify-content: flex-end; 557 justify-content: flex-end;
558 margin-left: 0 !important; 558 margin-left: 0 !important;
559 559
@@ -579,7 +579,7 @@ onMounted(() =&gt; { @@ -579,7 +579,7 @@ onMounted(() =&gt; {
579 width: 100%; 579 width: 100%;
580 text-align: center; 580 text-align: center;
581 font-size: 12px; 581 font-size: 12px;
582 - color: #999; 582 + color: #909399;
583 position: fixed; 583 position: fixed;
584 bottom: 60px; 584 bottom: 60px;
585 } 585 }
pages/mine/index.vue
1 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 - <!-- 顶部用户信息栏 --> 3 + <!-- 顶部用户信息栏:品牌渐变(设计稿 --grad-head) -->
4 <view class="header-bg"> 4 <view class="header-bg">
5 <up-avatar 5 <up-avatar
6 :src="'https://img.jichengshanshui.com.cn:28207/appimg/default-avatar.png'" 6 :src="'https://img.jichengshanshui.com.cn:28207/appimg/default-avatar.png'"
7 size="100rpx" 7 size="100rpx"
8 - shape="square" 8 + shape="circle"
9 class="user-avatar" 9 class="user-avatar"
10 ></up-avatar> 10 ></up-avatar>
11 11
12 - <!-- 用户名+手机号 --> 12 + <!-- 用户名+最近登录时间 -->
13 <view class="user-info-content"> 13 <view class="user-info-content">
14 <view class="user-name">{{ userStore.isLogin ? userInfo.nickname : '未登录' }}</view> 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 <view class="user-phone">上次登录时间 {{ timeFormat(userInfo.loginDate)}}</view> 15 <view class="user-phone">上次登录时间 {{ timeFormat(userInfo.loginDate)}}</view>
17 -  
18 </view> 16 </view>
19 -  
20 </view> 17 </view>
21 18
22 19
23 <view class="mine-content"> 20 <view class="mine-content">
24 - <up-cell-group title="个人信息"> 21 + <view class="card-title">个人信息</view>
  22 + <up-cell-group>
25 <up-cell title="姓名" :value="userInfo.nickname"></up-cell> 23 <up-cell title="姓名" :value="userInfo.nickname"></up-cell>
26 <up-cell title="账号" :value="userInfo.username"></up-cell> 24 <up-cell title="账号" :value="userInfo.username"></up-cell>
27 <up-cell title="电话" :value="userInfo.mobile"></up-cell> 25 <up-cell title="电话" :value="userInfo.mobile"></up-cell>
@@ -115,63 +113,111 @@ export default { @@ -115,63 +113,111 @@ export default {
115 </script> 113 </script>
116 114
117 <style lang="scss" scoped> 115 <style lang="scss" scoped>
  116 +/* 页面底:设计稿 --page-bg */
118 .page-container { 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 .header-bg { 125 .header-bg {
123 - position:relative;  
124 - top: 0;  
125 - left: 0; 126 + position: relative;
126 width: 100%; 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 display: flex; 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 .user-avatar { 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 .user-info-content { 191 .user-info-content {
146 - margin-left: 15px; 192 + margin-left: 24rpx;
147 flex: 1; 193 flex: 1;
  194 + min-width: 0;
148 195
149 .user-name { 196 .user-name {
150 - font-size: 16px;  
151 - font-weight: 600; 197 + font-size: 30rpx;
  198 + font-weight: 500;
152 color: #ffffff; 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 .user-phone { 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 .logout-btn-wrap { 210 .logout-btn-wrap {
164 - margin: 80px 15px 0; 211 + margin: 48rpx 24rpx 0;
165 } 212 }
166 -// 登录按钮 213 +// 登录 / 退出按钮:品牌蓝 + 16rpx 圆角(设计稿 .btn.pri.flat)
167 .login-btn { 214 .login-btn {
168 width: 100%; 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 </style> 223 </style>
178 \ No newline at end of file 224 \ No newline at end of file
pages/workbench/index.vue
@@ -511,7 +511,7 @@ watch(showDataLabel, () =&gt; { @@ -511,7 +511,7 @@ watch(showDataLabel, () =&gt; {
511 } 511 }
512 512
513 .grid-text { 513 .grid-text {
514 - font-size: 13px; 514 + font-size: 14px;
515 color: #1C1C1C; 515 color: #1C1C1C;
516 text-align: center; 516 text-align: center;
517 margin-top: 5px; 517 margin-top: 5px;
@@ -554,7 +554,7 @@ watch(showDataLabel, () =&gt; { @@ -554,7 +554,7 @@ watch(showDataLabel, () =&gt; {
554 text-align: center; 554 text-align: center;
555 padding: 60px 0; 555 padding: 60px 0;
556 font-size: 14px; 556 font-size: 14px;
557 - color: #999; 557 + color: #909399;
558 } 558 }
559 559
560 /* 图表+图例 左右布局核心样式 */ 560 /* 图表+图例 左右布局核心样式 */
@@ -603,8 +603,8 @@ watch(showDataLabel, () =&gt; { @@ -603,8 +603,8 @@ watch(showDataLabel, () =&gt; {
603 } 603 }
604 604
605 .legend-text { 605 .legend-text {
606 - font-size: 13px;  
607 - color: #333; 606 + font-size: 14px;
  607 + color: #1a1a1a;
608 /* 单行 + 溢出省略 */ 608 /* 单行 + 溢出省略 */
609 flex: 1; 609 flex: 1;
610 white-space: nowrap; 610 white-space: nowrap;
@@ -638,7 +638,7 @@ watch(showDataLabel, () =&gt; { @@ -638,7 +638,7 @@ watch(showDataLabel, () =&gt; {
638 .table-col { 638 .table-col {
639 flex: 1; 639 flex: 1;
640 text-align: center; 640 text-align: center;
641 - font-size: 13px; 641 + font-size: 14px;
642 display: flex; 642 display: flex;
643 align-items: center; 643 align-items: center;
644 justify-content: center; 644 justify-content: center;
uni.scss
1 /* uni.scss */ 1 /* uni.scss */
2 -@import '@/uni_modules/uview-plus/theme.scss';  
3 \ No newline at end of file 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;