project.vue 36 KB

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