attendance.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. <template>
  2. <div class="personTask">
  3. <el-row class="handle-box" style="margin-bottom: 10px">
  4. <el-row>
  5. <el-col :span="12">
  6. <!-- <el-select v-model="search.handleUserType" clearable filterable placeholder="组织" size="small"-->
  7. <!-- @change="groupChange">-->
  8. <!-- <el-option v-for="item in groupList" :key="item.value" :label="item.label" :value="item.value"/>-->
  9. <!-- </el-select>-->
  10. <!-- <el-select v-model="search.deptId" clearable filterable placeholder="部门" size="small">-->
  11. <!-- <el-option v-for="item in deptList" :key="item.value" :label="item.label" :value="item.value"/>-->
  12. <!-- </el-select>-->
  13. <el-input @change="handleSearch()" v-model="search.truename" class="ch-input ch-input-size"
  14. placeholder="姓名" size="small" clearable
  15. />
  16. <el-date-picker
  17. @change="handleSearch()"
  18. v-model="month"
  19. size="small"
  20. type="month"
  21. />
  22. </el-col>
  23. <el-col :span="12" style="text-align: right">
  24. <el-button class="ch-button-warning" size="small" @click="handleReset()"><i class="el-icon-search"/>&nbsp;重置
  25. </el-button>
  26. <el-button class="ch-button" size="small" @click="handleSearch()"><i class="el-icon-search"/>&nbsp;搜索
  27. </el-button>
  28. <el-button class="ch-button" size="small" @click="confirmOutput()"><i class="el-icon-menu"/>&nbsp;导出
  29. </el-button>
  30. </el-col>
  31. </el-row>
  32. </el-row>
  33. <el-row>
  34. <el-table
  35. ref="table"
  36. border
  37. v-loading="loading"
  38. :cell-class-name="cellClassName"
  39. :data="AllData"
  40. :header-cell-style="initTableHeaderStyle"
  41. :stripe="false"
  42. height="35vw"
  43. style="width: 100%"
  44. >
  45. <el-table-column align="center" fixed header-align="center" label="姓名" prop="truename"/>
  46. <el-table-column align="center" header-align="center" label="所在部门" prop="deptName" width="150"/>
  47. <el-table-column align="center" header-align="center" label="岗位" prop="postName" width="100"/>
  48. <el-table-column align="center" header-align="center" label="本月应勤天数" prop="workDay" width="50"/>
  49. <el-table-column align="center" header-align="center" label="本月实际出勤天数" prop="realityWorkDay"
  50. width="50"
  51. />
  52. <el-table-column align="center" header-align="center" label="其中:年假天数" prop="totalUseTime1" width="50"/>
  53. <el-table-column align="center" header-align="center" label="调休假(h)" prop="totalUseTime2" width="50"/>
  54. <el-table-column align="center" header-align="center" label="事假天数" prop="totalUseTime3" width="50"/>
  55. <el-table-column align="center" header-align="center" label="病假天数" prop="totalUseTime4" width="50"/>
  56. <el-table-column align="center" header-align="center" label="婚假天数" prop="totalUseTime5" width="50"/>
  57. <el-table-column align="center" header-align="center" label="产假天数" prop="totalUseTime6" width="50"/>
  58. <el-table-column align="center" header-align="center" label="陪产假天数" prop="totalUseTime7" width="50"/>
  59. <el-table-column align="center" header-align="center" label="丧假天数" prop="totalUseTime8" width="50"/>
  60. <el-table-column align="center" header-align="center" label="其中:加班(h)" prop="totalUseTime9" width="50"/>
  61. <el-table-column align="center" header-align="center" label="其中:迟到(次)" prop="totalUseTime10" width="50"/>
  62. <el-table-column align="center" header-align="center" label="其中:早退(次" prop="totalUseTime11" width="50"/>
  63. <el-table-column
  64. min-width="50px"
  65. v-for="(item,index) in headData"
  66. :key="index"
  67. :label="item.day.toString()"
  68. :prop="item.day.toString()"
  69. align="center"
  70. header-align="center"
  71. style="padding: 0"
  72. resizable
  73. >
  74. <el-table-column
  75. :key="headKey"
  76. :label="item.week"
  77. :prop="item.day.toString()"
  78. align="center"
  79. header-align="center"
  80. scoped-slot
  81. min-width="50px"
  82. resizable
  83. >
  84. <template slot="header">
  85. <span>{{ item.week }}</span>
  86. <span v-if="item.biq==='2'"
  87. style="color: blue;font-size: 12px; margin-left: 5px;position: absolute;bottom:50%;left:60%"
  88. >班</span>
  89. <span v-if="item.biq==='1'"
  90. style="color: red;font-size: 12px; margin-left: 5px;position: absolute;bottom:50%;left:60%;"
  91. >休</span>
  92. </template>
  93. <template slot-scope="scope">
  94. <div
  95. style="cursor:pointer;width: 100%;height: 20px;"
  96. class="chaochuyingcang"
  97. @click="personTaskDetail((scope.row.detailDayList[index]),scope.row.userId,item)"
  98. >
  99. <div v-html="getDetails(scope.row, index).badDayString" class="chaochuyingcang"></div>
  100. <div v-html="getDetails(scope.row, index).goodDayString" class="chaochuyingcang"></div>
  101. <!-- {{-->
  102. <!-- scope.row.detailDayList[index].happenTypesString === null ? "" : scope.row.detailDayList[index].happenTypesString-->
  103. <!-- }}-->
  104. </div>
  105. </template>
  106. </el-table-column>
  107. </el-table-column>
  108. </el-table>
  109. <div class="table-page">
  110. <el-pagination
  111. :current-page.sync="search.pageNum"
  112. :page-size="search.pageSize"
  113. :total="allpage"
  114. background
  115. layout="total, prev, pager, next"
  116. @current-change="handleCurrentChange"
  117. />
  118. </div>
  119. </el-row>
  120. <edit ref="edit" @getData="getData()"/>
  121. </div>
  122. </template>
  123. <script>
  124. import Base from '../base/base'
  125. import BaseData from '../base/baseData'
  126. import edit from '@/views/workflow/components/attendance/edit.vue'
  127. export default {
  128. name: 'BugLibrary',
  129. components: {
  130. edit
  131. },
  132. mixins: [Base, BaseData],
  133. data() {
  134. return {
  135. OutData: [],
  136. dc_key: ['BUG_TYPE', 'REPAIR_STATUS', 'EMERGENCY_DEGREE'],
  137. levelList: [1, 2, 3],
  138. trendsNumList: [],
  139. submitTime: [],
  140. AllData: [],
  141. headData: [],
  142. dialogBatchTaskTitle: '个人任务',
  143. dialogBatchVisible: false,
  144. loading: false,
  145. TaskAllData: '',
  146. dialogTitle: '',
  147. dialogVisible: false,
  148. taskFormKey: 0,
  149. taskFormKeys: 0,
  150. headKey: 0,
  151. groupList: [
  152. { value: '1', label: '内部' },
  153. { value: '2', label: '外部' }
  154. ],
  155. taskInfo: {
  156. id: '',
  157. batchId: '',
  158. proId: '',
  159. batchName: '',
  160. type: '1'
  161. },
  162. tableData: [],
  163. month: new Date(),
  164. checkList: '',
  165. onlineList: '',
  166. radio: 3,
  167. taskSearch: {},
  168. deptList: [],
  169. allpage: 0,
  170. search: {
  171. groupId: '',
  172. handleUserType: '',
  173. atMonth: '',
  174. deptId: '',
  175. name: '',
  176. proName: '',
  177. status: 0,
  178. online: '',
  179. handleUserId: '',
  180. pageNum: 1,
  181. pageSize: 12
  182. },
  183. hasAllPersonViewPermission: false,
  184. exportTable: []
  185. }
  186. },
  187. watch: {
  188. AllData: {
  189. handler() {
  190. this.$nextTick(() => {
  191. this.$refs.table.doLayout()
  192. })
  193. },
  194. deep: true,
  195. immediate: true
  196. }
  197. },
  198. mounted() {
  199. const _this = this
  200. this.initUser({ status: '1' })
  201. // _this.hasPermission()
  202. // _this.initUserAndDetp()
  203. // _this.initDepartment()
  204. // _this.initBizUser()
  205. this.initPost({ status: '0' })
  206. // _this.initProject()
  207. // _this.initBiz()
  208. this.initDict(_this.dc_key).then((res) => {
  209. // setTimeout(function() {
  210. // _this.getData();
  211. // }, 800);
  212. this.$nextTick(() => {
  213. _this.getData()
  214. })
  215. })
  216. },
  217. methods: {
  218. getDetails(e, index) {
  219. try {
  220. if (!e.detailDayList[index] || !e.detailDayList[index].happenTypesString) {
  221. return ''
  222. } else {
  223. let array = e.detailDayList[index].happenTypes.split(',')
  224. let type = [
  225. '年假', '调休', '事假',
  226. '病假', '婚假', '产假',
  227. '陪产假', '丧假', '加班',
  228. '迟到', '早退', '旷工',
  229. '外出', '居家', '出差'
  230. ]
  231. let badDay = []
  232. let goodDay = []
  233. for (let i = 0; i < array.length; i++) {
  234. if (array[i] == 10 || array[i] == 11 || array[i] == 12) {
  235. badDay.push(type[array[i] - 1])
  236. } else {
  237. goodDay.push(type[array[i] - 1])
  238. }
  239. }
  240. let badDayString = '<span style=\'color:red\'>' + badDay.join(',') + '</span>'
  241. let goodDayString = '<span style=\'color:blue\'>' + goodDay.join(',') + '</span>'
  242. return { badDayString, goodDayString }
  243. }
  244. } catch (a) {
  245. }
  246. },
  247. hasPermission() {
  248. if (this.$common.currUser() && this.$common.currUser().dataRoles && this.$common.currUser().dataRoles.DATA) {
  249. const permission = this.$common.currUser().dataRoles.DATA
  250. permission.forEach(item => {
  251. if (item === 'QYRW') {
  252. this.hasAllPersonViewPermission = true
  253. }
  254. })
  255. }
  256. },
  257. batchClose() {
  258. this.getData()
  259. },
  260. confirmOutput() {
  261. try {
  262. const _this = this
  263. this.OutData = []
  264. const title1 = [
  265. ' 姓名', ' 所在部门', '岗位', ' 本月应勤天数', '本月实际出勤天数', ' 其中:年假天数',
  266. ' 调休假(h)', ' 事假天数', ' 病假天数', '婚假天数', '产假天数',
  267. '陪产假天数', '丧假天数', '其中:加班(h)', ' 其中:迟到天数(次)', ' 其中:早退天数(次)']
  268. const title2 = [
  269. null, null, null, null, null,
  270. null, null, null, null, null,
  271. null, null, null, null, null, null
  272. ]
  273. _this.headData.forEach((item, index) => {
  274. title1.push(_this.$common.transDateStr(_this.month, 'yyyy/MM/') + item.day)
  275. title2.push(item.week)
  276. })
  277. this.OutData.push(title1)
  278. this.OutData.push(title2)
  279. const OutSize = []
  280. this.exportTable.forEach(function(item) {
  281. const jsonArray = []
  282. jsonArray.push(item.truename)
  283. jsonArray.push(item.deptName)
  284. jsonArray.push(item.postName)
  285. jsonArray.push(item.workDay)
  286. jsonArray.push(item.realityWorkDay)
  287. jsonArray.push(item.totalUseTime1)
  288. jsonArray.push(item.totalUseTime2)
  289. jsonArray.push(item.totalUseTime3)
  290. jsonArray.push(item.totalUseTime4)
  291. jsonArray.push(item.totalUseTime5)
  292. jsonArray.push(item.totalUseTime6)
  293. jsonArray.push(item.totalUseTime7)
  294. jsonArray.push(item.totalUseTime8)
  295. jsonArray.push(item.totalUseTime9)
  296. jsonArray.push(item.totalUseTime10)
  297. jsonArray.push(item.totalUseTime11)
  298. _this.headData.forEach(i => {
  299. console.log(item)
  300. console.log(item[(i.day) - 1])
  301. jsonArray.push(item.detailDayList[(i.day) - 1].happenTypesString)
  302. })
  303. _this.OutData.push(jsonArray)
  304. OutSize.push({ wch: 16 })
  305. })
  306. console.log(_this.OutData)
  307. const outMerges = [
  308. { s: { r: 0, c: 0 }, e: { r: 1, c: 0 } },
  309. { s: { r: 0, c: 1 }, e: { r: 1, c: 1 } },
  310. { s: { r: 0, c: 2 }, e: { r: 1, c: 2 } },
  311. { s: { r: 0, c: 3 }, e: { r: 1, c: 3 } },
  312. { s: { r: 0, c: 4 }, e: { r: 1, c: 4 } },
  313. { s: { r: 0, c: 5 }, e: { r: 1, c: 5 } },
  314. { s: { r: 0, c: 6 }, e: { r: 1, c: 6 } },
  315. { s: { r: 0, c: 7 }, e: { r: 1, c: 7 } },
  316. { s: { r: 0, c: 8 }, e: { r: 1, c: 8 } },
  317. { s: { r: 0, c: 9 }, e: { r: 1, c: 9 } },
  318. { s: { r: 0, c: 10 }, e: { r: 1, c: 10 } },
  319. { s: { r: 0, c: 11 }, e: { r: 1, c: 11 } },
  320. { s: { r: 0, c: 12 }, e: { r: 1, c: 12 } },
  321. { s: { r: 0, c: 13 }, e: { r: 1, c: 13 } },
  322. { s: { r: 0, c: 14 }, e: { r: 1, c: 14 } },
  323. { s: { r: 0, c: 15 }, e: { r: 1, c: 15 } }
  324. ]
  325. const fileName = '考勤表' + new Date().Format('yyyyMMddhhmm')
  326. console.log(this.OutData)
  327. this.$outputXlsxMergesFile(this.OutData, OutSize, outMerges, fileName)
  328. } catch (e) {
  329. console.warn(e)
  330. }
  331. },
  332. initTableHeaderStyle({ row, column, rowIndex, columnIndex }) {
  333. if (column.label === '周六' || column.label === '周日') {
  334. return 'background-color:#ffffff;color:rgba(0, 0, 0, 0.85);font-weight:500;'
  335. }
  336. if (!column.children) {
  337. } else {
  338. if (column.children && column.children[0].label === '周六' || column.children[0].label === '周日') {
  339. return 'background-color:#ffffff;color:rgba(0, 0, 0, 0.85);font-weight:500;'
  340. }
  341. }
  342. },
  343. // 判断周六周日给予特殊背景色
  344. cellClassName({ row, column, rowIndex, columnIndex }) {
  345. if (column.label === '周六' || column.label === '周日') {
  346. return 'warning-column'
  347. }
  348. },
  349. groupChange: function() {
  350. const _this = this
  351. _this.search.deptId = ''
  352. if (_this.search.handleUserType == '2') {
  353. _this.deptList = _this.BizData
  354. } else {
  355. _this.deptList = _this.DeptData
  356. }
  357. // _this.getData()
  358. },
  359. parentMethod: function(val) {
  360. if (val.length > 0) {
  361. this.form.handleUserId = val.join(',')
  362. }
  363. },
  364. getTaskData() {
  365. const _this = this
  366. _this.baseRequest('listAll', _this.taskSearch).then(res => {
  367. if (res.data) {
  368. const taskItems = []
  369. res.data.forEach(item => {
  370. taskItems.push(this.getTaskItemJson(item))
  371. })
  372. _this.TaskAllData = taskItems
  373. }
  374. })
  375. },
  376. getTaskItemJson(item) {
  377. item.requiredDate = this.$common.transDate(item.requiredDate)
  378. if (item.handleUserType === '1') {
  379. // item.handleGroupName = this.DeptUserNameMap[item.handleUserId]
  380. item.handleUserName = this.DeptUserMap[item.handleUserId]
  381. } else if (item.handleUserType === '2') {
  382. item.handleUserName = this.BizUserMap[item.handleUserId]
  383. // item.handleGroupName = this.BizUserNameMainMap[item.handleUserId]
  384. } else {
  385. item.handleUserName = this.DeptUserMap[item.handleUserId]
  386. }
  387. item.submitUserId = this.DeptUserMap[item.submitUserId]
  388. item.submitTime = this.$common.transServDate(item.submitTime)
  389. return item
  390. },
  391. getContent(content) {
  392. this.content = content
  393. this.form.content = content
  394. },
  395. personTaskDetail(val, day) {
  396. this.$refs.edit.setVisible(val, day)
  397. },
  398. changeTeam() {
  399. const _this = this
  400. _this.form.handleUserId = ''
  401. if (this.form.handleUserType == '1') {
  402. _this.handleUsers = _this.UserData
  403. } else {
  404. _this.handleUsers = _this.BizUserData
  405. }
  406. },
  407. openTaskForm() {
  408. const _this = this
  409. _this.taskFormKey++
  410. _this.taskInfo.id = ''
  411. _this.taskInfo.type = ''
  412. _this.taskInfo.isClone = false
  413. _this.dialogVisible = true
  414. },
  415. handleClose() {
  416. this.dialogVisible = false
  417. },
  418. handleCommit() {
  419. this.dialogVisible = false
  420. this.getData()
  421. },
  422. getData: function() {
  423. const _this = this
  424. _this.loading = true
  425. _this.AllData = []
  426. _this.search.handleUserId = _this.radio
  427. _this.search.date_from_1 = ''
  428. _this.search.date_to_1 = ''
  429. if (_this.submitTime !== null && _this.submitTime.length > 0) {
  430. _this.search.date_from_1 = _this.submitTime[0]
  431. _this.search.date_to_1 = _this.submitTime[1]
  432. }
  433. const currUser = _this.$common.currUser()
  434. console.log('currUsercurrUsercurrUser', currUser)
  435. if (currUser && currUser.groupId) {
  436. _this.search.groupId = this.$common.currUser().groupId
  437. }
  438. _this.search.atMonth = ''
  439. if (_this.month) {
  440. _this.search.atMonth = this.$common.transDate(_this.month, 'yyyy-MM')
  441. }
  442. try {
  443. this.baseRequest('selectInfoByMonth', _this.search).then((res) => {
  444. if (res.data) {
  445. _this.loading = false
  446. this.allpage = res.data.total
  447. res.data.rows.forEach(function(item) {
  448. const json = _this.getItemJson(item)
  449. _this.AllData.push(item)
  450. })
  451. _this.headKey++
  452. _this.headData = res.data.data
  453. }
  454. _this.loading = false
  455. }).catch(() => {
  456. })
  457. this.baseRequest('excelToselectInfoByMonth', _this.search).then((res) => {
  458. if (res.data) {
  459. _this.exportTable = res.data
  460. }
  461. }).catch(() => {
  462. })
  463. } catch (e) {
  464. }
  465. // this.initOutData()
  466. },
  467. getItemJson: function(item) {
  468. item.detailDayList.forEach((e, index, arr) => {
  469. item[index + 1] = e.happenTypesString
  470. })
  471. return item
  472. },
  473. handleSearch: function() {
  474. this.getData()
  475. },
  476. handleReset: function() {
  477. this.submitTime = []
  478. for (const i in this.search) {
  479. if (i !== 'pageNum' && i !== 'pageSize') {
  480. this.search[i] = ''
  481. }
  482. }
  483. this.search.status = 0
  484. this.month = new Date()
  485. this.radio = 1
  486. this.handleSearch()
  487. },
  488. /* 分页设定*/
  489. handleSizeChange: function(val) {
  490. this.search.pageSize = val
  491. this.getData()
  492. },
  493. handleCurrentChange: function(val) {
  494. this.search.pageNum = val
  495. this.getData()
  496. },
  497. baseRequest(opUrl, postData) {
  498. return this.$channel.globleRequest('WorkAttendanceLogController', opUrl, postData, 'project')
  499. }
  500. }
  501. }
  502. </script>
  503. <style lang="scss">
  504. .personTask {
  505. .chaochuyingcang {
  506. white-space: nowrap;
  507. overflow: hidden;
  508. text-overflow: ellipsis;
  509. }
  510. td {
  511. padding: 0
  512. }
  513. .ch-input .el-input__inner {
  514. border-radius: 0px;
  515. //border-color: #32323a;
  516. }
  517. .el-date-editor.el-input, .el-date-editor.el-input__inner {
  518. width: 150px !important;
  519. }
  520. .ch-input-size {
  521. width: 150px;
  522. }
  523. .ch-button {
  524. border-radius: 0px;
  525. border-color: #32323a;
  526. background-color: #32323a;
  527. color: #fff;
  528. }
  529. .ch-button-warning {
  530. margin-left: 10px;
  531. border-radius: 0px;
  532. border-color: #E75B5B;
  533. background-color: #E75B5B;
  534. color: #fff;
  535. }
  536. .ch-button-export {
  537. margin-left: 10px;
  538. border-radius: 0px;
  539. border-color: #98cc1f;
  540. background-color: #98cc1f;
  541. color: #fff;
  542. }
  543. .table1 {
  544. position: absolute;
  545. color: black;
  546. background-color: white;
  547. overflow: hidden;
  548. width: 100%;
  549. overflow: hidden;
  550. overflow-x: scroll;
  551. .hang {
  552. display: grid;
  553. justify-content: space-around;
  554. height: 48px;
  555. grid-template-columns: repeat(10, 1fr) repeat(31, 0.5fr);
  556. //margin: 10px 0;
  557. div {
  558. width: 100%;
  559. height: 100%;
  560. border: 1px solid black;
  561. display: flex;
  562. align-items: center;
  563. justify-content: center;
  564. }
  565. .changeCol {
  566. }
  567. }
  568. .firstHang {
  569. display: grid;
  570. height: 82px;
  571. grid-template-columns: repeat(10, 1fr) repeat(31, 0.5fr);
  572. div {
  573. width: 100%;
  574. height: 100%;
  575. //border:1px solid black;
  576. font-size: 12px;
  577. display: flex;
  578. align-items: center;
  579. justify-content: center;
  580. }
  581. .personData {
  582. display: grid;
  583. grid-template-columns: 1fr;
  584. p {
  585. border: 1px solid black;
  586. display: flex;
  587. align-items: center;
  588. justify-content: center;
  589. border-bottom: none;
  590. border-top: none;
  591. }
  592. }
  593. //.frData {
  594. // display: grid;
  595. // grid-template-columns: repeat(3, 1fr);
  596. // p {
  597. // border: 1px solid rgba(42, 57, 128, 0.3);
  598. // display: flex;
  599. // align-items: center;
  600. // justify-content: center;
  601. // border-bottom: none;
  602. // border-top: none;
  603. // }
  604. //}
  605. .cityData {
  606. display: grid;
  607. grid-template-columns: repeat(2, 1fr);
  608. p {
  609. border: 1px solid rgba(42, 57, 128, 0.3);
  610. display: flex;
  611. align-items: center;
  612. justify-content: center;
  613. border-bottom: none;
  614. border-top: none;
  615. }
  616. }
  617. .weekDay {
  618. display: flex;
  619. flex-direction: column;
  620. }
  621. .weekEnd {
  622. background: rgba(199, 25, 31, 0.25);
  623. div {
  624. }
  625. }
  626. }
  627. }
  628. .el-table th > .cell {
  629. overflow: visible !important;
  630. }
  631. .warning-column {
  632. background: rgba(245, 245, 245, 1) !important;
  633. }
  634. .cell {
  635. display: -webkit-box;
  636. -webkit-box-orient: vertical;
  637. overflow: hidden;
  638. -webkit-line-clamp: 2;
  639. text-overflow: ellipsis;
  640. }
  641. }
  642. </style>