jindu.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. <!-- saved from url=(0053)https://drp.idcgroup.com.cn:8082/BGJGZH/progress.html -->
  2. <html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  3. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  4. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  5. <script src="./file/axios.min.js"></script>
  6. <script src="./file/vue.min.js"></script>
  7. <link rel="stylesheet" href="./file/index.css">
  8. <script src="./file/vant.min.js"></script>
  9. <link rel="stylesheet" href="./file/style.css">
  10. <script src="./file/login-auth.js"></script>
  11. <title>进度</title>
  12. <style>
  13. body {
  14. background-color: #f5f6fa;
  15. margin: 0;
  16. font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', sans-serif;
  17. }
  18. .container {
  19. max-width: 750px;
  20. margin: 0 auto;
  21. background-color: #f5f6fa;
  22. min-height: 100vh;
  23. }
  24. /* 顶部导航栏 */
  25. .nav-bar {
  26. display: flex;
  27. justify-content: space-between;
  28. align-items: center;
  29. height: 44px;
  30. padding: 0 16px;
  31. background-color: #fff;
  32. border-bottom: 1px solid #eee;
  33. position: sticky;
  34. top: 0;
  35. z-index: 100;
  36. }
  37. .nav-bar .nav-left, .nav-bar .nav-right {
  38. width: 44px;
  39. height: 44px;
  40. display: flex;
  41. align-items: center;
  42. justify-content: center;
  43. cursor: pointer;
  44. }
  45. .nav-bar .nav-left svg, .nav-bar .nav-right svg {
  46. width: 20px;
  47. height: 20px;
  48. fill: #333;
  49. }
  50. .nav-bar .nav-right {
  51. gap: 16px;
  52. }
  53. .nav-bar .nav-title {
  54. font-size: 17px;
  55. font-weight: 600;
  56. color: #000;
  57. }
  58. /* 搜索栏 */
  59. .search-bar {
  60. display: flex;
  61. align-items: center;
  62. padding: 8px 12px;
  63. background-color: #fff;
  64. border-bottom: 1px solid #eee;
  65. }
  66. .search-input-wrap {
  67. flex: 1;
  68. display: flex;
  69. align-items: center;
  70. background-color: #f5f5f5;
  71. border-radius: 4px;
  72. padding: 6px 10px;
  73. }
  74. .search-input-wrap svg {
  75. width: 16px;
  76. height: 16px;
  77. fill: #999;
  78. margin-right: 6px;
  79. }
  80. .search-input-wrap input {
  81. flex: 1;
  82. border: none;
  83. background: transparent;
  84. outline: none;
  85. font-size: 14px;
  86. color: #333;
  87. }
  88. .search-cancel {
  89. margin-left: 12px;
  90. font-size: 14px;
  91. color: #1989fa;
  92. cursor: pointer;
  93. }
  94. /* 筛选弹窗 */
  95. .filter-mask {
  96. position: fixed;
  97. top: 0; left: 0; right: 0; bottom: 0;
  98. background: rgba(0,0,0,0.5);
  99. z-index: 999;
  100. }
  101. .filter-panel {
  102. position: fixed;
  103. top: 0;
  104. right: 0;
  105. bottom: 0;
  106. width: 85%;
  107. max-width: 350px;
  108. background: #fff;
  109. box-shadow: -2px 0 8px rgba(0,0,0,0.1);
  110. display: flex;
  111. flex-direction: column;
  112. z-index: 1000;
  113. transform: translateX(100%);
  114. transition: transform 0.3s ease;
  115. }
  116. .filter-panel.show {
  117. transform: translateX(0);
  118. }
  119. .filter-header {
  120. padding: 16px;
  121. display: flex;
  122. justify-content: space-between;
  123. align-items: center;
  124. border-bottom: 1px solid #eee;
  125. }
  126. .filter-header span { font-size: 17px; font-weight: 600; }
  127. .filter-close { font-size: 24px; color: #999; cursor: pointer; }
  128. .filter-body {
  129. flex: 1;
  130. overflow-y: auto;
  131. padding: 16px;
  132. }
  133. .filter-section {
  134. margin-bottom: 24px;
  135. }
  136. .filter-section-title {
  137. font-size: 14px;
  138. font-weight: 500;
  139. color: #333;
  140. margin-bottom: 12px;
  141. }
  142. .filter-tags {
  143. display: flex;
  144. flex-wrap: wrap;
  145. gap: 10px;
  146. }
  147. .tag-item {
  148. padding: 8px 16px;
  149. background: #f5f5f5;
  150. border-radius: 4px;
  151. font-size: 14px;
  152. color: #333;
  153. cursor: pointer;
  154. }
  155. .tag-item.active {
  156. background: #1989fa;
  157. color: #fff;
  158. }
  159. .filter-date-row {
  160. display: flex;
  161. align-items: center;
  162. gap: 10px;
  163. }
  164. .filter-date-row input {
  165. flex: 1;
  166. padding: 10px;
  167. border: 1px solid #ddd;
  168. border-radius: 4px;
  169. font-size: 14px;
  170. color: #333;
  171. background: #fff;
  172. }
  173. .filter-date-row span { color: #999; }
  174. .filter-footer {
  175. display: flex;
  176. padding: 16px;
  177. gap: 12px;
  178. border-top: 1px solid #eee;
  179. }
  180. .btn-reset {
  181. flex: 1;
  182. text-align: center;
  183. padding: 12px;
  184. border: 1px solid #ddd;
  185. border-radius: 4px;
  186. color: #1989fa;
  187. font-size: 15px;
  188. cursor: pointer;
  189. }
  190. .btn-confirm {
  191. flex: 1;
  192. text-align: center;
  193. padding: 12px;
  194. background: #1989fa;
  195. border-radius: 4px;
  196. color: #fff;
  197. font-size: 15px;
  198. cursor: pointer;
  199. }
  200. .tabNav {
  201. display: flex;
  202. background-color: #fff;
  203. border-bottom: 1px solid #eee;
  204. }
  205. .tabNav > a {
  206. display: block;
  207. flex: 1;
  208. text-align: center;
  209. line-height: 44px;
  210. font-size: 15px;
  211. color: #666;
  212. text-decoration: none;
  213. position: relative;
  214. }
  215. .tabNav > a.active {
  216. color: #1989fa;
  217. font-weight: 500;
  218. }
  219. .tabNav > a.active::after {
  220. content: '';
  221. position: absolute;
  222. bottom: 0;
  223. left: 50%;
  224. transform: translateX(-50%);
  225. width: 40px;
  226. height: 3px;
  227. background-color: #1989fa;
  228. border-radius: 2px;
  229. }
  230. .list-container {
  231. padding: 12px;
  232. background-color: #f5f6fa;
  233. }
  234. .card {
  235. background-color: #fff;
  236. border-radius: 8px;
  237. padding: 16px;
  238. margin-bottom: 12px;
  239. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
  240. }
  241. .card-header {
  242. display: flex;
  243. justify-content: space-between;
  244. align-items: center;
  245. padding-bottom: 12px;
  246. border-bottom: 1px solid #f0f0f0;
  247. }
  248. .tag {
  249. display: inline-block;
  250. background-color: #1989fa;
  251. color: #fff;
  252. font-size: 12px;
  253. padding: 4px 8px;
  254. border-radius: 4px;
  255. }
  256. .status {
  257. font-size: 14px;
  258. font-weight: 500;
  259. }
  260. .status.pending { color: #1989fa; }
  261. .status.processing { color: #07c160; }
  262. .status.completed { color: #ff976a; }
  263. .card-body {
  264. padding-top: 12px;
  265. }
  266. .address {
  267. font-size: 15px;
  268. font-weight: 500;
  269. color: #333;
  270. line-height: 1.5;
  271. margin-bottom: 8px;
  272. }
  273. .info-row {
  274. display: flex;
  275. font-size: 13px;
  276. color: #999;
  277. margin-bottom: 6px;
  278. line-height: 1.4;
  279. }
  280. .label {
  281. flex-shrink: 0;
  282. width: 70px;
  283. }
  284. .value {
  285. flex: 1;
  286. word-break: break-all;
  287. }
  288. .value.phone {
  289. color: #1989fa;
  290. text-decoration: none;
  291. }
  292. .empty-state {
  293. text-align: center;
  294. padding: 40px 0;
  295. color: #999;
  296. font-size: 14px;
  297. }
  298. </style>
  299. </head>
  300. <body>
  301. <div class="container">
  302. <div id="app6">
  303. <!-- 顶部导航栏 -->
  304. <div class="nav-bar">
  305. <div class="nav-left" @click="goback">
  306. <svg viewBox="0 0 24 24"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>
  307. </div>
  308. <div class="nav-title">进度查询</div>
  309. <div class="nav-right">
  310. <svg @click="showSearch = true" viewBox="0 0 24 24"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
  311. <svg @click="showFilter = true" viewBox="0 0 24 24"><path d="M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z"/></svg>
  312. </div>
  313. </div>
  314. <!-- 搜索栏 -->
  315. <div class="search-bar" v-show="showSearch">
  316. <div class="search-input-wrap">
  317. <svg viewBox="0 0 24 24"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
  318. <input type="text" v-model="searchKey" placeholder="请输入关键词搜索" />
  319. </div>
  320. <div class="search-cancel" @click="showSearch = false; searchKey = ''">取消</div>
  321. </div>
  322. <!-- 标签页导航 -->
  323. <div class="tabNav">
  324. <a class="active">预约单</a>
  325. <a href="gongdan.html">工单</a>
  326. </div>
  327. <div class="list-container">
  328. <div v-if="filteredList.length === 0" class="empty-state">暂无预约单数据</div>
  329. <div class="card" v-for="(item, index) in filteredList" :key="'res-'+index" @click="goDetail(item.sc_serviceformid)">
  330. <div class="card-header">
  331. <span class="tag">{{ item.type || '施工' }}</span>
  332. <span class="status" :class="{
  333. 'pending': item.status === '待处理',
  334. 'processing': item.status === '进行中',
  335. 'completed': item.status === '已完成'
  336. }">{{ item.status }}</span>
  337. </div>
  338. <div class="card-body">
  339. <div class="address">{{ item.address }}</div>
  340. <div class="info-row">
  341. <span class="label">预约单号:</span>
  342. <span class="value">{{ item.billno }}</span>
  343. </div>
  344. <div class="info-row">
  345. <span class="label">客户:</span>
  346. <span class="value">{{ item.name }} <a :href="'tel:' + item.phonenumber" class="value phone">{{ item.phonenumber }}</a></span>
  347. </div>
  348. <div class="info-row">
  349. <span class="label">指派时间:</span>
  350. <span class="value">{{ item.createdate || item.changedate }}</span>
  351. </div>
  352. <div class="info-row">
  353. <span class="label">经销商:</span>
  354. <span class="value">{{ item.remarks || item.createby }}</span>
  355. </div>
  356. </div>
  357. </div>
  358. </div>
  359. <!-- 筛选弹窗 - 预约单 -->
  360. <div class="filter-mask" v-show="showFilter" @click="showFilter = false">
  361. <div class="filter-panel" :class="{ show: showFilter }" @click.stop>
  362. <div class="filter-header">
  363. <span>筛选条件 (预约单)</span>
  364. <div class="filter-close" @click="showFilter = false">×</div>
  365. </div>
  366. <div class="filter-body">
  367. <div class="filter-section">
  368. <div class="filter-section-title">状态</div>
  369. <div class="filter-tags">
  370. <div class="tag-item" :class="{ active: filters.status === '待处理' }" @click="filters.status = '待处理'">待处理</div>
  371. <div class="tag-item" :class="{ active: filters.status === '进行中' }" @click="filters.status = '进行中'">进行中</div>
  372. <div class="tag-item" :class="{ active: filters.status === '待验收' }" @click="filters.status = '待验收'">待验收</div>
  373. <div class="tag-item" :class="{ active: filters.status === '已完成' }" @click="filters.status = '已完成'">已完成</div>
  374. </div>
  375. </div>
  376. <div class="filter-section">
  377. <div class="filter-section-title">服务类型</div>
  378. <div class="filter-tags">
  379. <div class="tag-item" :class="{ active: filters.type === '安装' }" @click="filters.type = '安装'">安装</div>
  380. <div class="tag-item" :class="{ active: filters.type === '维修' }" @click="filters.type = '维修'">维修</div>
  381. <div class="tag-item" :class="{ active: filters.type === '验收' }" @click="filters.type = '验收'">验收</div>
  382. </div>
  383. </div>
  384. <div class="filter-section">
  385. <div class="filter-section-title">创建时间</div>
  386. <div class="filter-date-row">
  387. <input type="date" v-model="filters.createDateStart" placeholder="开始日期" />
  388. <span>—</span>
  389. <input type="date" v-model="filters.createDateEnd" placeholder="结束日期" />
  390. </div>
  391. </div>
  392. <div class="filter-section">
  393. <div class="filter-section-title">完成时间</div>
  394. <div class="filter-date-row">
  395. <input type="date" v-model="filters.finishDateStart" placeholder="开始日期" />
  396. <span>—</span>
  397. <input type="date" v-model="filters.finishDateEnd" placeholder="结束日期" />
  398. </div>
  399. </div>
  400. </div>
  401. <div class="filter-footer">
  402. <div class="btn-reset" @click="resetFilter">重置</div>
  403. <div class="btn-confirm" @click="applyFilter">确定</div>
  404. </div>
  405. </div>
  406. </div>
  407. </div>
  408. </div>
  409. <script>
  410. new Vue({
  411. el: '#app6',
  412. data: {
  413. dataList: [],
  414. showSearch: false,
  415. searchKey: '',
  416. showFilter: false,
  417. filters: {
  418. status: '',
  419. type: '',
  420. createDateStart: '',
  421. createDateEnd: '',
  422. finishDateStart: '',
  423. finishDateEnd: ''
  424. }
  425. },
  426. computed: {
  427. filteredList () {
  428. return this.dataList;
  429. }
  430. },
  431. watch: {
  432. showFilter (val) {
  433. if (val) {
  434. document.body.classList.add('van-overflow-hidden');
  435. } else {
  436. document.body.classList.remove('van-overflow-hidden');
  437. }
  438. }
  439. },
  440. methods: {
  441. goback () {
  442. window.location.href="javascript:history.go(-1)";
  443. },
  444. goDetail (id) {
  445. window.location.href = 'detail.html?id=' + id;
  446. },
  447. resetFilter () {
  448. this.filters = { status: '', type: '', createDateStart: '', createDateEnd: '', finishDateStart: '', finishDateEnd: '' };
  449. this.getData();
  450. },
  451. applyFilter () {
  452. this.showFilter = false;
  453. this.getData();
  454. },
  455. getData() {
  456. var self = this;
  457. var login = window.H5Login || {};
  458. axios.post(window.API_URL, {
  459. id: 2026052013163202,
  460. content: {
  461. phonenumber: login.phone || '',
  462. pageNumber: 1,
  463. pageSize: 50,
  464. where: {
  465. condition: this.searchKey || '',
  466. status: this.filters.status ? [this.filters.status] : [],
  467. type: this.filters.type || '',
  468. begindate_createdate: this.filters.createDateStart || '',
  469. enddate_createdate: this.filters.createDateEnd || '',
  470. begindate_finishdate: this.filters.finishDateStart || '',
  471. enddate_finishdate: this.filters.finishDateEnd || ''
  472. }
  473. },
  474. accesstoken: login.token || ''
  475. }).then(function (res) {
  476. var data = res.data;
  477. if (data.code === 1) {
  478. self.dataList = data.data || [];
  479. }
  480. }).catch(function () {
  481. self.dataList = [];
  482. });
  483. }
  484. },
  485. mounted() {
  486. var self = this;
  487. this.getData();
  488. window.addEventListener('h5:login', function () {
  489. self.getData();
  490. });
  491. }
  492. })
  493. </script></body></html>