project.vue 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. <template>
  2. <div class="w-main project">
  3. <v-title>{{$L('项目')}}</v-title>
  4. <div class="w-nav">
  5. <div class="nav-row">
  6. <div class="w-nav-left">
  7. <div class="page-nav-left">
  8. <span class="hover" @click="addShow=true"><i class="ft icon">&#xE740;</i> {{$L('新建项目')}}</span>
  9. <div v-if="loadIng > 0" class="page-nav-loading"><w-loading></w-loading></div>
  10. <div v-else class="page-nav-refresh"><em @click="getLists(true)">{{$L('刷新')}}</em></div>
  11. </div>
  12. </div>
  13. <div class="w-nav-flex"></div>
  14. <div class="w-nav-right m768-show">
  15. <Dropdown @on-click="handleProject" trigger="click" transfer>
  16. <Icon type="md-menu" size="18"/>
  17. <DropdownMenu slot="list">
  18. <DropdownItem name="myjoin">{{$L('参与的项目')}}</DropdownItem>
  19. <DropdownItem name="myfavor">{{$L('收藏的项目')}}</DropdownItem>
  20. <DropdownItem name="mycreate">{{$L('我管理的项目')}}</DropdownItem>
  21. </DropdownMenu>
  22. </Dropdown>
  23. </div>
  24. <div class="w-nav-right m768-hide">
  25. <span class="ft hover" @click="handleProject('myjoin', null)"><i class="ft icon">&#xE75E;</i> {{$L('参与的项目')}}</span>
  26. <span class="ft hover" @click="handleProject('myfavor', null)"><i class="ft icon">&#xE720;</i> {{$L('收藏的项目')}}</span>
  27. <span class="ft hover" @click="handleProject('mycreate', null)"><i class="ft icon">&#xE764;</i> {{$L('我管理的项目')}}</span>
  28. </div>
  29. </div>
  30. </div>
  31. <w-content>
  32. <!-- 列表 -->
  33. <ul class="project-list">
  34. <li v-for="item in lists">
  35. <div class="project-item">
  36. <div class="project-head">
  37. <div v-if="item.loadIng === true" class="project-loading">
  38. <w-loading></w-loading>
  39. </div>
  40. <div class="project-title" v-if="item.type == 0" @click="handleProject('open', item)">{{item.title}}</div>
  41. <div class="project-title" v-if="item.type == 1" @click="handleProject('look', item)">{{item.title}}</div>
  42. <div class="project-setting" v-if="item.type == 0">
  43. <Dropdown class="right-info" trigger="click" @on-click="handleProject($event, item)" transfer>
  44. <Icon class="project-setting-icon" type="md-settings" size="16"/>
  45. <Dropdown-menu slot="list">
  46. <Dropdown-item name="open">{{$L('打开')}}</Dropdown-item>
  47. <Dropdown-item name="favor">{{$L('收藏')}}</Dropdown-item>
  48. <Dropdown-item v-if="item.isowner" name="rename">{{$L('重命名')}}</Dropdown-item>
  49. <Dropdown-item v-if="item.isowner" name="transfer">{{$L('移交项目')}}</Dropdown-item>
  50. <Dropdown-item v-if="item.isowner" name="move">{{$L('移动项目')}}</Dropdown-item>
  51. <Dropdown-item v-if="item.isowner" name="delete">{{$L('删除')}}</Dropdown-item>
  52. <Dropdown-item v-else name="out">{{$L('退出')}}</Dropdown-item>
  53. </Dropdown-menu>
  54. </Dropdown>
  55. </div>
  56. <div class="project-setting" v-if="item.type == 1 && isAdmin">
  57. <Dropdown class="right-info" trigger="click" @on-click="handleProject($event, item)" transfer>
  58. <Icon class="project-setting-icon" type="md-settings" size="16"/>
  59. <Dropdown-menu slot="list">
  60. <Dropdown-item name="rename">{{$L('重命名')}}</Dropdown-item>
  61. <Dropdown-item name="move">{{$L('移动')}}</Dropdown-item>
  62. <Dropdown-item name="delete">{{$L('删除')}}</Dropdown-item>
  63. </Dropdown-menu>
  64. </Dropdown>
  65. </div>
  66. </div>
  67. <div class="project-num" v-if="item.type == 0" @click="handleProject('open', item)">
  68. <div class="project-circle">
  69. <i-circle
  70. :size="100"
  71. :trail-width="8"
  72. :stroke-width="8"
  73. :percent="selfProportion(item.self_complete, item.self_count)"
  74. stroke-linecap="round"
  75. stroke-color="#62C5FE">
  76. <div class="project-circle-box">
  77. <div class="project-circle-num">
  78. <em>{{item.self_complete}}</em>
  79. <span>{{item.self_count}}</span>
  80. </div>
  81. <div class="project-circle-title">{{$L('个人总计')}}</div>
  82. </div>
  83. </i-circle>
  84. </div>
  85. <div class="project-situation">
  86. <ul>
  87. <li>{{$L('项目总任务数')}}<em>{{item.complete + item.unfinished}}</em></li>
  88. <li>{{$L('项目已完成数')}}<em>{{item.complete}}</em></li>
  89. <li>{{$L('项目未完成数')}}<em>{{item.unfinished}}</em></li>
  90. </ul>
  91. </div>
  92. </div>
  93. <div v-if="item.type == 1" @click="handleProject('look', item)" style="height:181px;display:flex;flex:1;flex-direction:row;align-items:center;justify-content:center;cursor: pointer">
  94. <img src="/images/statics/images/folder.png" width="100" style="position:relative;z-index: 10" />
  95. </div>
  96. <div class="project-bottom" v-if="item.type == 0">
  97. <div class="project-iconbtn">
  98. <Icon class="project-iconbtn-icon" type="md-stats" />
  99. <div class="project-iconbtn-text" @click.stop="handleProject('statistics', item)">{{$L('项目统计')}}</div>
  100. </div>
  101. <div class="project-iconbtn">
  102. <Icon class="project-iconbtn-icon" type="md-filing"/>
  103. <div class="project-iconbtn-text" @click.stop="handleProject('archived', item)">{{$L('已归档任务')}}</div>
  104. </div>
  105. <div class="project-iconbtn project-people" @click.stop="handleProject('member', item)">
  106. <UserImg v-for="(uItem, uKey) in item.people_lists" class="userimg-icon" :key="uKey" :info="uItem" two-words show-title/>
  107. <div v-if="item.people_count > 99" class="userimg-count" :title="item.people_count">99+</div>
  108. <div v-else-if="item.people_count > 5" class="userimg-count">{{item.people_count}}</div>
  109. </div>
  110. </div>
  111. </div>
  112. </li>
  113. </ul>
  114. <!-- 分页 -->
  115. <Page v-if="listTotal > 0" class="pageBox" :total="listTotal" :current="listPage" :disabled="loadIng > 0" :pageSize="listPageSize" @on-change="setPage" @on-page-size-change="setPageSize" :page-size-opts="[20,40,60,100]" placement="top" transfer show-elevator show-sizer show-total :simple="windowMax768"></Page>
  116. </w-content>
  117. <Modal
  118. v-model="addShow"
  119. :title="$L('新建项目')"
  120. :closable="false"
  121. :mask-closable="false"
  122. class-name="simple-modal">
  123. <Form ref="add" :model="formAdd" :rules="ruleAdd" :label-width="80" @submit.native.prevent>
  124. <FormItem prop="title" :label="$L('项目名称')">
  125. <Input type="text" v-model="formAdd.title"></Input>
  126. </FormItem>
  127. <FormItem prop="type" :label="$L('项目类型')">
  128. <RadioGroup v-model="formAdd.type">
  129. <Radio label="1">文件夹</Radio>
  130. <Radio label="0">项目</Radio>
  131. </RadioGroup>
  132. </FormItem>
  133. <FormItem prop="labels" :label="$L('项目模板')" v-if="this.formType == 0">
  134. <Select v-model="formAdd.template" @on-change="(res) => {$set(formAdd, 'labels', labelLists[res].value)}">
  135. <Option v-for="(item, index) in labelLists" :value="index" :key="index">{{ item.label }}</Option>
  136. </Select>
  137. </FormItem>
  138. <FormItem :label="$L('项目流程')" v-if="this.formType == 0">
  139. <div style="line-height:38px">
  140. <span v-for="(item, index) in formAdd.labels">
  141. <span v-if="index > 0">&gt;</span>
  142. <Tag @on-close="() => { formAdd.labels.splice(index, 1)}" closable size="large" color="primary">{{item}}</Tag>
  143. </span>
  144. </div>
  145. <div v-if="formAdd.labels.length > 0" style="margin-top:4px;"></div>
  146. <div style="margin-bottom:-16px">
  147. <Button icon="ios-add" type="dashed" @click="addLabels">{{$L('添加流程')}}</Button>
  148. </div>
  149. </FormItem>
  150. </Form>
  151. <div slot="footer">
  152. <Button type="default" @click="addShow=false">{{$L('取消')}}</Button>
  153. <Button type="primary" :loading="loadIng > 0" @click="onAdd">{{$L('添加')}}</Button>
  154. </div>
  155. </Modal>
  156. <WDrawer v-model="projectDrawerShow" maxWidth="1000">
  157. <Tabs v-if="projectDrawerShow" v-model="projectDrawerTab">
  158. <TabPane :label="$L('已归档任务')" name="archived">
  159. <project-archived :canload="projectDrawerShow && projectDrawerTab == 'archived'" :projectid="handleProjectId"></project-archived>
  160. </TabPane>
  161. <TabPane :label="$L('项目统计')" name="statistics">
  162. <project-statistics :canload="projectDrawerShow && projectDrawerTab == 'statistics'" :projectid="handleProjectId"></project-statistics>
  163. </TabPane>
  164. <TabPane :label="$L('成员管理')" name="member">
  165. <project-users :canload="projectDrawerShow && projectDrawerTab == 'member'" :projectid="handleProjectId"></project-users>
  166. </TabPane>
  167. </Tabs>
  168. </WDrawer>
  169. <WDrawer v-model="projectListDrawerShow" maxWidth="740">
  170. <Tabs v-if="projectListDrawerShow" v-model="projectListDrawerTab">
  171. <TabPane :label="$L('参与的项目')" name="myjoin">
  172. <project-my-join :canload="projectListDrawerShow && projectListDrawerTab == 'myjoin'"></project-my-join>
  173. </TabPane>
  174. <TabPane :label="$L('收藏的项目')" name="myfavor">
  175. <project-my-favor :canload="projectListDrawerShow && projectListDrawerTab == 'myfavor'"></project-my-favor>
  176. </TabPane>
  177. <TabPane :label="$L('管理的项目')" name="mycreate">
  178. <project-my-manage :canload="projectListDrawerShow && projectListDrawerTab == 'mycreate'"></project-my-manage>
  179. </TabPane>
  180. </Tabs>
  181. </WDrawer>
  182. </div>
  183. </template>
  184. <style lang="scss" scoped>
  185. .project {
  186. ul.project-list {
  187. padding: 5px;
  188. max-width: 2200px;
  189. margin: 0 auto;
  190. li {
  191. float: left;
  192. width: 20%;
  193. display: flex;
  194. @media (max-width: 2000px) {
  195. width: 25%;
  196. }
  197. @media (max-width: 1400px) {
  198. width: 33.33%;
  199. }
  200. @media (max-width: 1080px) {
  201. width: 50%;
  202. }
  203. @media (max-width: 640px) {
  204. width: 100%;
  205. }
  206. .project-item {
  207. flex: 1;
  208. margin: 10px;
  209. width: 100%;
  210. height: 313px;
  211. padding: 20px;
  212. background-color: #ffffff;
  213. border-radius: 4px;
  214. display: flex;
  215. flex-direction: column;
  216. .project-head{
  217. display: flex;
  218. flex-direction: row;
  219. .project-loading {
  220. width: 18px;
  221. height: 18px;
  222. margin-right: 6px;
  223. margin-top: 3px;
  224. }
  225. .project-title{
  226. flex: 1;
  227. font-size: 16px;
  228. padding-right: 6px;
  229. overflow:hidden;
  230. text-overflow:ellipsis;
  231. white-space:nowrap;
  232. color: #333333;
  233. cursor: pointer;
  234. }
  235. .project-setting{
  236. width: 30px;
  237. text-align: right;
  238. .project-setting-icon {
  239. cursor: pointer;
  240. color: #333333;
  241. &:hover {
  242. color: #0396f2;
  243. }
  244. }
  245. }
  246. }
  247. .project-num {
  248. flex: 1;
  249. padding: 34px 0;
  250. display: flex;
  251. flex-direction: row;
  252. align-items: center;
  253. justify-content: center;
  254. cursor: pointer;
  255. position: relative;
  256. &:before {
  257. content: "";
  258. position: absolute;
  259. width: 1px;
  260. height: 60%;
  261. background-color: #EFEFEF;
  262. }
  263. .project-circle {
  264. flex: 1;
  265. text-align: center;
  266. margin-right: 10px;
  267. .project-circle-box {
  268. display: flex;
  269. flex-direction: column;
  270. align-items: center;
  271. justify-content: center;
  272. .project-circle-num {
  273. display: flex;
  274. align-items: flex-end;
  275. font-weight: 600;
  276. em {
  277. color: #62C5FE;
  278. font-size: 26px;
  279. }
  280. span {
  281. color: #666666;
  282. &:before {
  283. content: "/";
  284. }
  285. }
  286. }
  287. .project-circle-title {
  288. font-size: 12px;
  289. padding-top: 4px;
  290. color: #999999;
  291. }
  292. }
  293. }
  294. .project-situation {
  295. flex: 1;
  296. position: relative;
  297. ul {
  298. display: flex;
  299. flex-direction: column;
  300. position: absolute;
  301. top: 50%;
  302. left: 50%;
  303. transform: translate(-50%, -50%);
  304. > li {
  305. width: 100%;
  306. color: #BBBBBB;
  307. font-size: 12px;
  308. white-space: nowrap;
  309. display: flex;
  310. align-items: center;
  311. padding: 6px 0;
  312. line-height: 20px;
  313. > em {
  314. padding-left: 14px;
  315. font-size: 18px;
  316. color: #666666;
  317. font-weight: 500;
  318. }
  319. }
  320. }
  321. }
  322. }
  323. .project-bottom {
  324. display: flex;
  325. flex-direction: column;
  326. border-top: 1px solid #EFEFEF;
  327. padding: 18px 0;
  328. cursor: default;
  329. position: relative;
  330. .project-iconbtn {
  331. flex: 1;
  332. width: 50%;
  333. text-align: center;
  334. display: flex;
  335. align-items: center;
  336. padding: 4px 0;
  337. &.project-people {
  338. width: auto;
  339. min-width: 36px;
  340. position: absolute;
  341. bottom: 18px;
  342. right: 0;
  343. cursor: pointer;
  344. justify-content: flex-end;
  345. .userimg-icon,
  346. .userimg-count {
  347. width: 36px;
  348. height: 36px;
  349. border-radius: 18px;
  350. margin-left: -16px;
  351. border: 2px solid #ffffff;
  352. }
  353. .userimg-count {
  354. transform: scale(1);
  355. color: #ffffff;
  356. font-size: 16px;
  357. font-weight: 500;
  358. line-height: 32px;
  359. background-color: #62C5FE;
  360. }
  361. }
  362. .project-iconbtn-icon {
  363. font-size: 16px;
  364. margin-right: 6px;
  365. color: #999;
  366. }
  367. .project-iconbtn-text {
  368. color: #999999;
  369. cursor: pointer;
  370. &:hover {
  371. color: #0396f2;
  372. }
  373. }
  374. }
  375. }
  376. }
  377. }
  378. &:before,
  379. &:after {
  380. display: table;
  381. content: "";
  382. }
  383. &:after {
  384. clear: both;
  385. }
  386. }
  387. }
  388. </style>
  389. <script>
  390. import Vue from 'vue'
  391. import TagInput from '../components/TagInput'
  392. Vue.component('TagInput', TagInput)
  393. import WContent from "../components/WContent";
  394. import ProjectArchived from "../components/project/archived";
  395. import ProjectUsers from "../components/project/users";
  396. import ProjectStatistics from "../components/project/statistics";
  397. import ProjectMyFavor from "../components/project/my/favor";
  398. import ProjectMyJoin from "../components/project/my/join";
  399. import ProjectMyManage from "../components/project/my/manage";
  400. import Project from "../mixins/project";
  401. import WDrawer from "../components/iview/WDrawer";
  402. export default {
  403. components: {
  404. WDrawer,
  405. ProjectMyManage,
  406. ProjectMyJoin,
  407. ProjectMyFavor, ProjectStatistics, ProjectUsers, ProjectArchived, WContent},
  408. mixins: [
  409. Project
  410. ],
  411. data () {
  412. return {
  413. loadIng: 0,
  414. addShow: false,
  415. formAdd: {
  416. title: '',
  417. labels: [],
  418. template: 0,
  419. pid:0
  420. },
  421. ruleAdd: {},
  422. labelLists: [],
  423. lists: [],
  424. listPage: 1,
  425. listTotal: 0,
  426. listPageSize: 20,
  427. projectDrawerShow: false,
  428. projectDrawerTab: 'archived',
  429. projectListDrawerShow: false,
  430. projectListDrawerTab: 'myjoin',
  431. handleProjectId: 0,
  432. pid:0,
  433. isAdmin: false,
  434. formType: 1
  435. }
  436. },
  437. mounted() {
  438. let params = this.$route.params;
  439. this.pid = params.pid;
  440. this.getLists(true);
  441. //
  442. $A.setOnTaskInfoListener('pages/project',(act, detail) => {
  443. let item = this.lists.find((item) => { return item.id == detail.projectid });
  444. if (!item) {
  445. return;
  446. }
  447. const persons = detail.persons ? !!detail.persons.find(({username}) => username == this.usrName) : null;
  448. const unfinishedNum = (add) => {
  449. if (add) {
  450. item.unfinished++;
  451. persons === true && item.self_count++;
  452. } else {
  453. item.unfinished--;
  454. persons === true && item.self_count--;
  455. }
  456. };
  457. const completeNum = (add) => {
  458. if (add) {
  459. item.complete++;
  460. persons === true && item.self_complete++;
  461. } else {
  462. item.complete--;
  463. persons === true && item.self_complete--;
  464. }
  465. };
  466. switch (act) {
  467. case 'deleteproject': // 删除项目
  468. case 'deletelabel': // 删除分类
  469. this.getLists(true);
  470. break;
  471. case "create": // 创建任务
  472. unfinishedNum(true);
  473. break;
  474. case "delete": // 删除任务
  475. case "archived": // 归档
  476. if (detail.complete) {
  477. completeNum();
  478. } else {
  479. unfinishedNum();
  480. }
  481. break;
  482. case "unarchived": // 取消归档
  483. if (detail.complete) {
  484. completeNum(true);
  485. } else {
  486. unfinishedNum(true);
  487. }
  488. break;
  489. case "complete": // 标记完成
  490. completeNum(true);
  491. unfinishedNum();
  492. break;
  493. case "unfinished": // 标记未完成
  494. completeNum();
  495. unfinishedNum(true);
  496. break;
  497. }
  498. }, true);
  499. this.isAdmin = $A.identity('admin');
  500. },
  501. deactivated() {
  502. this.addShow = false;
  503. this.projectDrawerShow = false;
  504. this.projectListDrawerShow = false;
  505. },
  506. watch: {
  507. usrName() {
  508. this.usrLogin && this.getLists(true);
  509. },
  510. '$route' (To) {
  511. if (To.name == 'project-pid') {
  512. this.pid = To.params.pid;
  513. }else{
  514. this.pid = 0;
  515. }
  516. },
  517. pid(val){
  518. this.formAdd.pid = val;
  519. this.listPage = 1;
  520. this.listPageSize = 20;
  521. this.getLists(true);
  522. },
  523. 'formAdd.type'(val){
  524. this.formType = val
  525. }
  526. },
  527. methods: {
  528. initLanguage() {
  529. this.labelLists = [{
  530. label: this.$L('空白模板'),
  531. value: [],
  532. }, {
  533. label: this.$L('工作流'),
  534. value: [this.$L('未启动'), this.$L('进行中'), this.$L('已完成'), this.$L('已搁置')],
  535. }, {
  536. label: this.$L('时间流'),
  537. value: [this.$L('第一季度'), this.$L('第二季度'), this.$L('第三季度'), this.$L('第四季度'), this.$L('已搁置')],
  538. }];
  539. this.ruleAdd = {
  540. title: [
  541. { required: true, message: this.$L('请填写项目名称!'), trigger: 'change' },
  542. { type: 'string', min: 2, message: this.$L('项目名称至少2个字!'), trigger: 'change' }
  543. ],
  544. type: [
  545. { required: true, message: this.$L('请选择项目类型!'), trigger: 'change' }
  546. ]
  547. };
  548. },
  549. setPage(page) {
  550. this.listPage = page;
  551. this.getLists();
  552. },
  553. setPageSize(size) {
  554. if (Math.max($A.runNum(this.listPageSize), 20) != size) {
  555. this.listPageSize = size;
  556. this.getLists();
  557. }
  558. },
  559. getLists(resetLoad) {
  560. if (resetLoad === true) {
  561. this.listPage = 1;
  562. }
  563. this.loadIng++;
  564. $A.apiAjax({
  565. url: 'project/lists',
  566. data: {
  567. page: Math.max(this.listPage, 1),
  568. pagesize: Math.max($A.runNum(this.listPageSize), 20),
  569. pid: this.pid
  570. },
  571. complete: () => {
  572. this.loadIng--;
  573. },
  574. success: (res) => {
  575. if (res.ret === 1) {
  576. this.lists = res.data.lists;
  577. this.listTotal = res.data.total;
  578. }else{
  579. this.lists = [];
  580. this.listTotal = 0;
  581. }
  582. }
  583. });
  584. },
  585. addLabels() {
  586. this.labelsValue = "";
  587. this.$Modal.confirm({
  588. render: (h) => {
  589. return h('div', [
  590. h('div', {
  591. style: {
  592. fontSize: '16px',
  593. fontWeight: '500',
  594. marginBottom: '20px',
  595. }
  596. }, this.$L('添加流程')),
  597. h('TagInput', {
  598. props: {
  599. value: this.labelsValue,
  600. autofocus: true,
  601. placeholder: this.$L('请输入流程名称,多个可用英文逗号分隔。')
  602. },
  603. on: {
  604. input: (val) => {
  605. this.labelsValue = val;
  606. }
  607. }
  608. })
  609. ])
  610. },
  611. onOk: () => {
  612. if (this.labelsValue) {
  613. let array = $A.trim(this.labelsValue).split(",");
  614. array.forEach((name) => {
  615. if ($A.trim(name)) {
  616. this.formAdd.labels.push($A.trim(name));
  617. }
  618. });
  619. }
  620. },
  621. })
  622. },
  623. onAdd() {
  624. this.$refs.add.validate((valid) => {
  625. if (valid) {
  626. this.loadIng++;
  627. $A.apiAjax({
  628. url: 'project/add',
  629. data: this.formAdd,
  630. complete: () => {
  631. this.loadIng--;
  632. },
  633. success: (res) => {
  634. if (res.ret === 1) {
  635. this.addShow = false;
  636. this.$Message.success(res.msg);
  637. this.$refs.add.resetFields();
  638. this.$set(this.formAdd, 'template', 0);
  639. //
  640. this.getLists(true);
  641. } else {
  642. this.$Modal.error({title: this.$L('温馨提示'), content: res.msg});
  643. }
  644. }
  645. });
  646. }
  647. });
  648. },
  649. openComplete(item) {
  650. if (item.complete > 0) {
  651. this.openProject(item.id, item, '已完成')
  652. } else {
  653. this.handleProject('open', item);
  654. }
  655. },
  656. handleProject(event, item) {
  657. if (item) {
  658. this.handleProjectId = item.id;
  659. }
  660. switch (event) {
  661. case 'favor': {
  662. this.favorProject('add', item.id);
  663. break;
  664. }
  665. case 'rename': {
  666. this.renameProject(item);
  667. break;
  668. }
  669. case 'transfer': {
  670. this.transferProject(item);
  671. break;
  672. }
  673. case 'move': {
  674. this.moveProject(item);
  675. break;
  676. }
  677. case 'delete': {
  678. this.deleteProject(item.id, () => {
  679. this.getLists();
  680. });
  681. break;
  682. }
  683. case 'out': {
  684. this.outProject(item.id, () => {
  685. this.getLists();
  686. });
  687. break;
  688. }
  689. case 'open': {
  690. this.openProject(item.id, item);
  691. break;
  692. }
  693. case 'archived':
  694. case 'member':
  695. case 'statistics': {
  696. this.projectDrawerShow = true;
  697. this.projectDrawerTab = event;
  698. break;
  699. }
  700. case 'myjoin':
  701. case 'myfavor':
  702. case 'mycreate': {
  703. this.projectListDrawerShow = true;
  704. this.projectListDrawerTab = event;
  705. break;
  706. }
  707. case 'look': {
  708. this.lookProject(item.id, item);
  709. break;
  710. }
  711. }
  712. },
  713. renameProject(item) {
  714. this.renameValue = "";
  715. this.$Modal.confirm({
  716. render: (h) => {
  717. return h('div', [
  718. h('div', {
  719. style: {
  720. fontSize: '16px',
  721. fontWeight: '500',
  722. marginBottom: '20px',
  723. }
  724. }, this.$L('重命名项目')),
  725. h('Input', {
  726. props: {
  727. value: this.renameValue,
  728. autofocus: true,
  729. placeholder: this.$L('请输入新的项目名称')
  730. },
  731. on: {
  732. input: (val) => {
  733. this.renameValue = val;
  734. }
  735. }
  736. })
  737. ])
  738. },
  739. loading: true,
  740. onOk: () => {
  741. if (this.renameValue) {
  742. this.$set(item, 'loadIng', true);
  743. let title = this.renameValue;
  744. $A.apiAjax({
  745. url: 'project/rename',
  746. data: {
  747. projectid: item.id,
  748. title: title,
  749. },
  750. complete: () => {
  751. this.$set(item, 'loadIng', false);
  752. },
  753. error: () => {
  754. this.$Modal.remove();
  755. alert(this.$L('网络繁忙,请稍后再试!'));
  756. },
  757. success: (res) => {
  758. this.$Modal.remove();
  759. this.$set(item, 'title', title);
  760. setTimeout(() => {
  761. if (res.ret === 1) {
  762. this.$Message.success(res.msg);
  763. } else {
  764. this.$Modal.error({title: this.$L('温馨提示'), content: res.msg});
  765. }
  766. }, 350);
  767. }
  768. });
  769. } else {
  770. this.$Modal.remove();
  771. }
  772. },
  773. });
  774. },
  775. transferProject(item) {
  776. this.transferValue = "";
  777. this.$Modal.confirm({
  778. render: (h) => {
  779. return h('div', [
  780. h('div', {
  781. style: {
  782. fontSize: '16px',
  783. fontWeight: '500',
  784. marginBottom: '20px',
  785. }
  786. }, this.$L('移交项目')),
  787. h('UserInput', {
  788. props: {
  789. value: this.transferValue,
  790. nousername: item.username,
  791. placeholder: this.$L('请输入昵称/用户名搜索')
  792. },
  793. on: {
  794. input: (val) => {
  795. this.transferValue = val;
  796. }
  797. }
  798. })
  799. ])
  800. },
  801. loading: true,
  802. onOk: () => {
  803. if (this.transferValue) {
  804. this.$set(item, 'loadIng', true);
  805. let username = this.transferValue;
  806. $A.apiAjax({
  807. url: 'project/transfer',
  808. data: {
  809. projectid: item.id,
  810. username: username,
  811. },
  812. complete: () => {
  813. this.$set(item, 'loadIng', false);
  814. },
  815. error: () => {
  816. this.$Modal.remove();
  817. alert(this.$L('网络繁忙,请稍后再试!'));
  818. },
  819. success: (res) => {
  820. this.$Modal.remove();
  821. this.getLists();
  822. setTimeout(() => {
  823. if (res.ret === 1) {
  824. this.$Message.success(res.msg);
  825. } else {
  826. this.$Modal.error({title: this.$L('温馨提示'), content: res.msg});
  827. }
  828. }, 350);
  829. }
  830. });
  831. } else {
  832. this.$Modal.remove();
  833. }
  834. },
  835. });
  836. },
  837. moveProject(item) {
  838. this.loadIng++;
  839. $A.apiAjax({
  840. url: 'project/lists',
  841. data: {
  842. isfloder: 1,
  843. pid: item.pid
  844. },
  845. complete: () => {
  846. this.loadIng--;
  847. },
  848. success: (res) => {
  849. if (res.ret === 1) {
  850. this.folders = res.data;
  851. this.moveValue = "";
  852. this.$Modal.confirm({
  853. render: (h) => {
  854. return h('div', [
  855. h('div', {
  856. style: {
  857. fontSize: '16px',
  858. fontWeight: '500',
  859. marginBottom: '20px',
  860. }
  861. }, this.$L('移动')),
  862. h('Select', {
  863. props: {
  864. value: this.moveValue,
  865. transfer: true,
  866. },
  867. on: {
  868. 'on-change': (val) => {
  869. this.moveValue = val;
  870. }
  871. }
  872. },
  873. this.folders.map((obj)=>{
  874. if(obj.id != item.id){
  875. return h('Option', {
  876. props: {value: obj.id}
  877. },obj.title);
  878. }
  879. }))
  880. ])
  881. },
  882. loading: true,
  883. onOk: () => {
  884. if (this.moveValue) {
  885. this.$set(item, 'loadIng', true);
  886. let moveValue = this.moveValue;
  887. $A.apiAjax({
  888. url: 'project/move',
  889. data: {
  890. projectid: item.id,
  891. pid: moveValue,
  892. },
  893. complete: () => {
  894. this.$set(item, 'loadIng', false);
  895. },
  896. error: () => {
  897. this.$Modal.remove();
  898. alert(this.$L('网络繁忙,请稍后再试!'));
  899. },
  900. success: (res) => {
  901. this.$Modal.remove();
  902. this.getLists();
  903. setTimeout(() => {
  904. if (res.ret === 1) {
  905. this.$Message.success(res.msg);
  906. } else {
  907. this.$Modal.error({title: this.$L('温馨提示'), content: res.msg});
  908. }
  909. }, 350);
  910. }
  911. });
  912. } else {
  913. this.$Modal.remove();
  914. }
  915. },
  916. });
  917. }
  918. }
  919. });
  920. },
  921. selfProportion(complete, count) {
  922. if (count <= 0) {
  923. return 100;
  924. }
  925. return Math.round(complete / count * 100)
  926. }
  927. },
  928. }
  929. </script>