CopyTarget.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. <template>
  2. <el-dialog :title="title" :visible.sync="visible_" :close-on-click-modal="false" :before-close="close_before" top="5%" append-to-body @open="openDialog" width="760px">
  3. <div>
  4. <div class="flex-box-ce stepNew flex-center-center">
  5. <div class="stepOneN" :class="{tabActive:tabIndex == 1,accomplish:accomplish==1||accomplish==2 }">
  6. <div><i class="el-icon-check" style="padding-right: 5px;" v-if="accomplish==1||accomplish==2"></i>复制基本信息</div>
  7. <span></span>
  8. </div>
  9. <div class="stepThreeN" :class="{tabActive:tabIndex == 2,accomplish:accomplish==2||accomplish==3 }">
  10. <span></span>
  11. <div><i class="el-icon-check" style="padding-right: 5px;" v-if="accomplish==2||accomplish==3"></i>复制KR</div>
  12. <span></span>
  13. </div>
  14. </div>
  15. <template v-if="tabIndex==1">
  16. <el-form ref="form" :model="form" label-width="80px" class="form">
  17. <el-form-item label="名称">
  18. <el-input type="textarea" autosize class="noBorder" v-model="form.name" placeholder="最多能输入100字" clearable maxlength="100" show-word-limit></el-input>
  19. </el-form-item>
  20. <el-form-item label="周期">
  21. <div class="border flex-box-ce">
  22. <div class="flex-1" style="color: #606266;">{{addDateParameter2.year}}年 {{addDateParameter2.name}}</div>
  23. <i class="el-icon-arrow-down icon-right"></i>
  24. <div class="inputDc" @click="isShowZq=true"></div>
  25. </div>
  26. <!-- <el-radio-group v-model="form.cycle_type">
  27. <el-radio :label="1">年度</el-radio>
  28. <el-radio :label="3">半年度</el-radio>
  29. <el-radio :label="2">季度</el-radio>
  30. <el-radio :label="4">月度</el-radio>
  31. </el-radio-group>
  32. <div class="flex-box-ce">
  33. <el-select v-model="form.year" placeholder="请选择" style="margin-right: 10px;">
  34. <el-option v-for="item in yearArr" :key="item.value" :label="item.label" :value="item.value"></el-option>
  35. </el-select>
  36. <el-select v-model="form.half_year" placeholder="请选择" v-show="form.cycle_type==3">
  37. <el-option v-for="item in halfYearArr" :key="item.value" :label="item.label" :value="item.value"></el-option>
  38. </el-select>
  39. <el-select v-model="form.quarter" placeholder="请选择" v-show="form.cycle_type==2">
  40. <el-option v-for="item in seasonArr" :key="item.value" :label="item.label" :value="item.value"></el-option>
  41. </el-select>
  42. <el-select v-model="form.month" placeholder="请选择" v-show="form.cycle_type==4">
  43. <el-option v-for="item in monthArr" :key="item.value" :label="item.label" :value="item.value"></el-option>
  44. </el-select>
  45. </div> -->
  46. </el-form-item>
  47. <el-form-item label="目标类型">
  48. <div class="border flex-box-ce" @click="isShowTargetType=true">
  49. <div class="flex-1" style="color: #606266;">{{getBelongType(form.belong_type).label}}</div>
  50. <i class="el-icon-arrow-down icon-right"></i>
  51. <TargetType :visible.sync="isShowTargetType" :deptId='form.dept_id' :belong_type="form.belong_type" @confirm="selectTargetType" trigger="manual"><div class="inputDc"></div></TargetType>
  52. </div>
  53. </el-form-item>
  54. <el-form-item label="负责人">
  55. <div class="flex-box-ce">
  56. <div class="flex-box-ce cursor" @click="selectUser(1)">
  57. <userImage :user_name="form.owner_userInfo.name" :img_url="form.owner_userInfo.img_url" width="30px" height="30px" fontSize="12" ></userImage>
  58. <span style="padding-left: 5px;" >{{form.owner_userInfo.name}}</span>
  59. </div>
  60. </div>
  61. </el-form-item>
  62. <el-form-item label="参与人">
  63. <div class="cursor" style="border-radius: 4px;border: 1px solid #dcdfe6;line-height: 34px;width: 300px;padding: 0 15px;" @click="selectUserAll(1)">
  64. <div class="flex-box-ce fontColorB font-flex-word" v-if="form.joiner_items.length>0">
  65. <span v-for="item in form.joiner_items"> {{item.name}},</span>
  66. </div>
  67. <div v-else style="color: #C0C4CF;">请选择参与人员</div>
  68. </div>
  69. </el-form-item>
  70. <el-form-item label="可见范围">
  71. <el-select v-model="form.visible_type" style="width: 300px;" placeholder="请选择">
  72. <el-option v-for="item in getScopeArr" :key="item.value" :label="item.label" :value="item.value" ></el-option>
  73. </el-select>
  74. <div class="border flex-box-ce" style="margin-top: 5px;" @click="show_dept_selector=true" v-if="form.visible_type==5">
  75. <div class="flex-1">
  76. <div class="fontColorB font-flex-word" style="width: 230px;" v-if="dept_selected.dept.length>0">
  77. <span v-for="item in dept_selected.dept" :key="item.id">{{item.dept_name}},</span>
  78. </div>
  79. <span v-else class="fontColorC">请选择部门</span>
  80. </div>
  81. <i class="el-icon-arrow-down icon-right" style="padding-right:0px ;"></i>
  82. <div class="inputDc"></div>
  83. </div>
  84. <div class="border flex-box-ce" style="margin-top: 5px;" v-if="form.visible_type==4">
  85. <div class="flex-1">
  86. <div class="fontColorB font-flex-word" style="width: 260px;" v-if="form.special_employee_items.length>0">
  87. <span v-for="item in form.special_employee_items" :key="item.id">{{item.name}},</span>
  88. </div>
  89. <span v-else>请选择成员</span>
  90. </div>
  91. <i class="el-icon-arrow-down icon-right"></i>
  92. <div class="inputDc" @click="selectUserAll(2)"></div>
  93. </div>
  94. </el-form-item>
  95. <el-form-item label="对齐目标">
  96. <div class="border flex-box-ce">
  97. <div class="flex-1">
  98. <span style="color: #606266;" v-if="alignItem.name">{{alignItem.name}}</span>
  99. <span v-else>选择对齐上级目标</span>
  100. </div>
  101. <i class="el-icon-error icon-right" v-if="alignItem.name" @click="alignItem={}"></i>
  102. <i class="el-icon-arrow-down icon-right" v-else></i>
  103. <div class="inputDc" @click.stop="isShowDateSearch=true" style="right: 30px;"></div>
  104. </div>
  105. </el-form-item>
  106. </el-form>
  107. </template>
  108. <template v-if="tabIndex==2">
  109. <div style="margin: 20px 0">
  110. <div style="height: 500px;overflow-y: scroll;" class="scroll-bar">
  111. <div class="flex-box-ce add-task-item" v-for="(item,index) in krs" :key="index">
  112. <i class="el-icon-delete-solid" @click="deleteKr(index)" style="width: 30px;height: 30px;text-align: center;line-height: 30px;font-size: 16px;opacity: 0;"></i>
  113. <div class="flex-box-ce flex-1" style="border-bottom: 1px solid #f1f1f1;padding:5px 8px;">
  114. <div style="font-size: 16px;font-weight: 600;" class="fontColorB">KR{{index+1}}</div>
  115. <div class="flex-1"><el-input placeholder="请输入可衡量的关键成果" clearable v-model.trim="item.name" maxlength="100" show-word-limit></el-input></div>
  116. <el-popover placement="bottom" trigger="click">
  117. <div>
  118. <el-input @input="[(item.weight = isFloor(item.weight))]" @blur="inputBlur(item)" placeholder="请输入权重(1~100)" v-model="item.weight"><span slot="append">%</span></el-input>
  119. </div>
  120. <div slot="reference" class="weight"><i class="el-icon-pie-chart"></i><span style="">{{item.weight}}</span>%</div>
  121. </el-popover>
  122. <div class="flex-box-ce cursor" @click="selectUser(2,item,index)">
  123. <userImage :user_name="item.userInfo.name" :img_url="item.userInfo.img_url" width="30px" height="30px" fontSize="12"></userImage>
  124. <span style="padding-left: 5px;">{{item.userInfo.name}}</span>
  125. </div>
  126. </div>
  127. </div>
  128. <div class="flex-box-ce flex-box-end" style="margin-top: 20px;padding-left: 36px;">
  129. <div class="fontColorC hoverBlue" @click="addKr"><i class="el-icon-plus"></i><span style="padding-left: 5px;">添加KR</span></div>
  130. <div class="flex-1"></div>
  131. <!-- <div class="fontColorC" style="font-size: 12px;margin-right: 20px;">总权重:{{getKrWeight}}%</div>
  132. <el-button round type="primary" size="mini" @click="pingJun">平均权重</el-button> -->
  133. </div>
  134. </div>
  135. </div>
  136. </template>
  137. <template v-if="tabIndex==3">
  138. <div style="margin: 20px 0">
  139. <div class="flex-box-ce" style="background-color: #FEF2DF;padding:5px 10px;margin-bottom: 20px;">
  140. <span style="padding-right: 20px;">是否复制目标下的任务</span>
  141. <el-radio-group v-model="isCopyTask">
  142. <el-radio :label="1">复制一级任务</el-radio>
  143. <el-radio :label="2">复制全部任务</el-radio>
  144. <el-radio :label="2">不复制</el-radio>
  145. </el-radio-group>
  146. </div>
  147. <div style="height: 500px;overflow-y: scroll;" class="scroll-bar">
  148. <div style="background-color: #F5F8FA;padding: 10px;border-radius: 5px;margin-bottom: 10px;" v-for="(item,index) in [1,2,3]">
  149. <div class="flex-box-ce flex-d-center" style="margin-bottom: 10px;">
  150. <div class="flex-box-ce">
  151. <userImage :id="userInfo.id" width="40px" height="40px" :user_name="userInfo.name"></userImage>
  152. <span style="margin-left: 10px;font-size: 14px;color: #3F4755;">{{ userInfo.name }}</span>
  153. </div>
  154. <el-date-picker :clearable="false" size="small" v-model="date" type="daterange" range-separator="~" start-placeholder="开始日期"end-placeholder="结束日期"></el-date-picker>
  155. </div>
  156. <el-input type="textarea" autosize class="noBorder noBj" v-model="form.name" placeholder="最多能输入300字" clearable></el-input>
  157. </div>
  158. </div>
  159. </div>
  160. </template>
  161. </div>
  162. <div class="flex-box-ce flex-box-end" style="margin-top: 20px;">
  163. <el-button @click="close">取 消</el-button>
  164. <el-button type="primary" @click="addTab(true)" v-if="tabIndex<2">下一步</el-button>
  165. <el-button type="primary" @click="addTab(false)" v-else>上一步</el-button>
  166. <el-button type="primary" @click="confirmAddTarget" v-if="tabIndex==2">确 定</el-button>
  167. </div>
  168. <EmployeeSelector :isRequired="true" :isChecKedAll="false" :can_select_employee="false" :can_select_dept="true" :multi="true" :selected="dept_selected" :visible.sync="show_dept_selector"@confirm="dept_confirm"/>
  169. <!-- 对齐目标 -->
  170. <TargetSearch :visible.sync="isShowDateSearch" @confirm="confirmTarget" :id="alignItem.id"></TargetSearch>
  171. <!-- 选择负责人 -->
  172. <EmployeeSelector :is_filtration_creator="false" title="选择人员" :isChecKedAll="false" :isRequired="true" :multi="false" :selected="employee_selected" :visible.sync="show_employee_selector" @confirm="employee_confirm"/>
  173. <!-- 选择负责人 -->
  174. <EmployeeSelector :is_filtration_creator="false" title="选择人员" :isRequired="isRequired" :selected="employee_selected_all" :visible.sync="show_employee_selector_all" @confirm="employee_confirm_all"/>
  175. <!-- 创建周期 -->
  176. <el-dialog title="选择周期" :visible.sync="isShowZq" :append-to-body="true" width="500px">
  177. <div style="margin: 15px 0;">
  178. <div class="flex-box-ce" style="margin-bottom: 16px;">
  179. <div class="black" style="width: 60px;">周期</div>
  180. <div class="border flex-box-ce">
  181. <div class="flex-1" style="color: #606266;">{{addDateParameter.year}}年 {{addDateParameter.name}}</div>
  182. <i class="el-icon-arrow-down icon-right"></i>
  183. <SelectPeriod :dateParameter="addDateParameter" @confirm="dateConfirm" :id="2" :isShowAll="false"><div class="inputDc"></div></SelectPeriod>
  184. </div>
  185. </div>
  186. <div class="flex-box-ce">
  187. <div class="black" style="width: 60px;">日期</div>
  188. <div>
  189. <el-date-picker
  190. v-model="monthDateVal"
  191. type="daterange"
  192. range-separator="至"
  193. :clearable="false"
  194. start-placeholder="开始日期"
  195. end-placeholder="结束日期"
  196. value-format="yyyy-MM-dd"
  197. ></el-date-picker>
  198. </div>
  199. </div>
  200. </div>
  201. <div class="flex-box-end" style="margin-top: 50px;">
  202. <el-button @click="isShowZq=false">取消</el-button>
  203. <el-button type="primary" plain @click="activeZq">确定</el-button>
  204. </div>
  205. </el-dialog>
  206. </el-dialog>
  207. </template>
  208. <script>
  209. import {getYearArr,getScopeArr,getBelongType,getDateStr} from '@/okr/utils/auth';
  210. import EmployeeSelector from '@/components/EmployeeSelector';
  211. import TargetType from '@/okr/components/public/TargetType'; //目标类型
  212. import TargetSearch from '@/okr/components/public/TargetSearch'; //对齐目标
  213. import SelectPeriod from '@/okr/components/public/SelectPeriod'; //input组件
  214. export default {
  215. name: 'CopyTarget',
  216. components:{TargetSearch,EmployeeSelector,TargetType,SelectPeriod},
  217. props: {
  218. title: {
  219. // 标题
  220. type: String,
  221. default: '复制目标'
  222. },
  223. visible: {
  224. // 是否显示组件
  225. type: Boolean,
  226. default: false
  227. },
  228. id:{ //id o_id或者kr_Id
  229. type: Number,
  230. default: 0
  231. },
  232. },
  233. data() {
  234. return {
  235. userInfo: this.$userInfo(),
  236. getScopeArr:getScopeArr(),
  237. getBelongType:getBelongType,
  238. form: {owner_userInfo:{},joiner_userInfos:[],joiner_items:[],special_employee_items:[]},
  239. isShowDateSearch:false,
  240. alignItem:{},
  241. employee_selected_all: { dept: [], employee: [] },
  242. show_employee_selector_all: false,
  243. selectUserIndex:0,//选人组件 区分不同地方调用组件的标识
  244. employee_selected: { dept: [], employee: [] },
  245. show_employee_selector: false,
  246. isShowTargetType:false,
  247. isCopyKr:true,
  248. isCopyTask:true,
  249. krs:[],
  250. selectKrIndex:'',
  251. selectUserIndex2:0,//选人组件 区分不同地方调用组件的标识
  252. date:'',
  253. tabIndex: 1,
  254. accomplish:0,
  255. visible_: false,
  256. yearArr:getYearArr(),
  257. seasonArr:[{value: 1,label: '第一季度'},{value: 2,label: '第二季度'},{value: 3,label: '第三季度'},{value: 4,label: '第四季度'}],
  258. halfYearArr:[{value: 1,label: '上半年'},{value: 2,label: '下半年'}],
  259. monthArr:[],
  260. sumWeight:0,
  261. // 部门可见
  262. deptVisibleName: null,
  263. dept_selected: {dept: [],employee:[]},
  264. show_dept_selector: false,
  265. dept_tree:[],
  266. depts:[],
  267. isRequired:true,
  268. isShowZq:false,
  269. addDateParameter:{year:this.$moment().format('YYYY'),cycle_type:4,dateId:this.$moment().format('M'),name:`${this.$moment().format('M')}月`},
  270. monthDateVal:[this.$moment().startOf('month').format('YYYY-MM-DD'),this.$moment().endOf('month').format('YYYY-MM-DD')],//添加目标周期日期
  271. addDateParameter2:{year:this.$moment().format('YYYY'),cycle_type:4,dateId:this.$moment().format('M'),name:`${this.$moment().format('M')}月`},
  272. monthDateVal2:[this.$moment().startOf('month').format('YYYY-MM-DD'),this.$moment().endOf('month').format('YYYY-MM-DD')],//添加目标周期日期
  273. };
  274. },
  275. computed:{
  276. getKrWeight(){
  277. let sumWeight=0;
  278. this.krs.forEach(item=>{
  279. sumWeight+=Number(item.weight)
  280. })
  281. this.sumWeight= Math.round(sumWeight)
  282. return this.sumWeight;
  283. }
  284. },
  285. watch: {
  286. visible(val) {
  287. this.visible_ = JSON.parse(JSON.stringify(val));
  288. if(this.id){
  289. this.tabIndex= 1;
  290. this.accomplish=1;
  291. this.getTargetDateil()
  292. }
  293. },
  294. isShowZq(val){
  295. if(val){
  296. this.addDateParameter=JSON.parse(JSON.stringify(this.addDateParameter2));
  297. this.monthDateVal=JSON.parse(JSON.stringify(this.monthDateVal2));
  298. }
  299. },
  300. },
  301. methods: {
  302. activeZq(){
  303. this.addDateParameter2=JSON.parse(JSON.stringify(this.addDateParameter));
  304. this.monthDateVal2=JSON.parse(JSON.stringify(this.monthDateVal));
  305. this.isShowZq=false;
  306. },
  307. //选择周期
  308. dateConfirm(item){
  309. this.addDateParameter=item;
  310. let startDate='',endDate=''
  311. if(item.cycle_type==1){
  312. startDate = `${item.year}-01-01`
  313. endDate = `${item.year}-12-31`
  314. }
  315. if(item.cycle_type==3){// 上半年,下半年
  316. let dateStr=item.year+'-'
  317. startDate = item.year+'-'+(item.dateId==1? '01-01':'07-01')
  318. endDate = item.year+'-'+(item.dateId==1? '06-30': '12-31')
  319. }
  320. if(item.cycle_type==2){// 指定年指定季度的开始结束时间:(某年某季度的开始结束时间)
  321. let dateStr=item.year+'-'
  322. let str=item.dateId==1? '01-01':item.dateId==2? '04-01':item.dateId==3? '07-01':item.dateId==4? '10-01':''
  323. startDate = dateStr+str;
  324. endDate = this.$moment(this.$moment().format(dateStr+str)).endOf('quarter').format("YYYY-MM-DD")
  325. }
  326. if(item.cycle_type==4){// 指定年指定季度的开始结束时间:(某年某季度的开始结束时间)
  327. startDate = this.$moment(`${item.dateId}/${item.year}`, 'MM/YYYY').add(0, 'M').format('YYYY-MM-DD');
  328. endDate = this.$moment(`${item.dateId}/${item.year}`, 'MM/YYYY').endOf('M').add(0, 'M').format('YYYY-MM-DD');
  329. }
  330. this.monthDateVal=[startDate,endDate]
  331. },
  332. isAllEqual(array) {
  333. if (array.length > 0) {
  334. return !array.some(function(value, index) {
  335. return value !== array[0];
  336. });
  337. } else {
  338. return true;
  339. }
  340. },
  341. deleteKr(index){
  342. this.krs.splice(index,1);
  343. // this.$nextTick(()=>{
  344. // let weights=this.krs.map(item=>{
  345. // return Number(item.weight)
  346. // })
  347. // if(this.isAllEqual(weights)){
  348. // let weight=(100/(this.krs.length)).toFixed(2)
  349. // this.krs.forEach(item=>{
  350. // item.weight=weight
  351. // })
  352. // }
  353. // })
  354. },
  355. addKr(){
  356. let sumWeight=0;
  357. let weights=this.krs.map(item=>{
  358. sumWeight+=Number(item.weight)
  359. return Number(item.weight)
  360. })
  361. let weight=Math.floor((100/(this.krs.length+1)) * 100) / 100
  362. let obj={name:'',weight:100,owner_id:this.userInfo.id,userInfo:this.userInfo};
  363. // if(this.isAllEqual(weights)){
  364. // this.krs.forEach(item=>{
  365. // item.weight=weight
  366. // })
  367. // obj.weight=weight;
  368. // }else{
  369. // obj.weight=100-sumWeight>0? 100-sumWeight:0;
  370. // }
  371. this.$nextTick(()=>{
  372. this.krs.push(obj)
  373. })
  374. },
  375. // 部门可见
  376. dept_confirm(data){
  377. let dept_ids = [];
  378. this.dept_selected = data
  379. data.dept.forEach(element => {
  380. dept_ids.push(element.dept_id)
  381. });
  382. this.form.special_dept_ids=dept_ids;
  383. },
  384. pingJun(){
  385. let weight=Math.floor((100/(this.krs.length)) * 100) / 100
  386. this.krs.forEach(item=>{
  387. item.weight=weight
  388. })
  389. },
  390. inputBlur(item) {
  391. if (item.weight === null||item.weight === undefined||item.weight === '') {
  392. item.weight = 0;
  393. }
  394. },
  395. isFloor(el) {
  396. var obj = event.target;
  397. el = el
  398. .replace('.', '$#$') //把第一个字符'.'替换成'$#$'
  399. .replace(/\./g, '') //把其余的字符'.'替换为空
  400. .replace('$#$', '.') //把字符'$#$'替换回原来的'.'
  401. .replace(/[^\d.]/g, '') //只能输入数字和'.'
  402. .replace(/^\./g, '') //不能以'.'开头
  403. .replace(/([0-9]+\.[0-9]{2})[0-9]*/, '$1'); //只保留2位小数
  404. if(el=='01'||el=='02'||el=='03'||el=='04'||el=='05'||el=='06'||el=='07'||el=='08'||el=='09'){
  405. el=el[1]
  406. }
  407. return el || null;
  408. },
  409. employee_confirm_all(val){
  410. let users=val.employee
  411. if(this.selectUserIndex==1){
  412. this.form.joiner_items=users;
  413. this.form.joiner_ids=users.map(item=>{
  414. return item.id
  415. })
  416. }else if(this.selectUserIndex==2){
  417. this.form.special_employee_items=users;
  418. this.form.special_employee_ids=users.map(item=>{
  419. return item.id
  420. })
  421. }
  422. },
  423. selectUserAll(index){
  424. if(index==1){//参与者
  425. this.isRequired=false;
  426. this.employee_selected_all.employee=this.form.joiner_items
  427. }else if(index==2){//可见范围
  428. this.isRequired=true;
  429. this.employee_selected_all.employee=this.form.special_employee_items
  430. }
  431. this.selectUserIndex=index;//选人组件 区分不同地方调用组件的标识
  432. this.show_employee_selector_all=true;
  433. },
  434. selectUser(type,item,index){
  435. if(type==2){
  436. this.employee_selected.employee=[item.userInfo];
  437. this.selectKrIndex=index;
  438. }else{
  439. this.employee_selected.employee=[this.form.owner_userInfo];
  440. }
  441. this.selectUserIndex2=type;
  442. this.show_employee_selector=true;
  443. },
  444. employee_confirm(val){
  445. let user=val.employee[0]
  446. if(this.selectUserIndex2==1){
  447. this.form.owner_userInfo=user;
  448. this.form.owner_id=user.id;
  449. }else{
  450. this.krs[this.selectKrIndex].userInfo=user
  451. this.krs[this.selectKrIndex].owner_id=user.id
  452. }
  453. },
  454. confirmAddTarget(){
  455. let isError=false;
  456. let krs=[];
  457. this.krs.some(item=>{
  458. krs.push({
  459. name:item.name,
  460. owner_id:item.owner_id,
  461. weight:item.weight*100,
  462. })
  463. if(!item.name){
  464. this.$message.error("KR关键成果不能为空");
  465. isError=true;
  466. return true
  467. }
  468. })
  469. if(isError){return false}
  470. // if(this.sumWeight!=100){
  471. // this.$message.error("KR权重之和必须为100%");
  472. // return false
  473. // }
  474. let params={
  475. obj_name:this.form.name, //目标名称 最多100个字符
  476. obj_owner_id:this.form.owner_id, //负责人ID
  477. kr:JSON.stringify(krs), //见下面json示例
  478. cycle_type:this.addDateParameter2.cycle_type, //循环周期 1年 2 季度 3半年 4月度
  479. visible_type:this.form.visible_type, //可见范围 1 全公司 2 相关人员 3 下属 4指定人员
  480. special_employee_ids:JSON.stringify(this.form.special_employee_ids), //相关人员可见时,必填,由员工ID组成的json数组
  481. special_dept_ids:JSON.stringify(this.form.special_dept_ids), //相关人员可见时,必填,由员工ID组成的json数组
  482. join_ids:this.form.joiner_ids.toString(),
  483. belong_type:this.form.belong_type, //归属类型 1 公司 2 部门 3 团队 4 个人
  484. dept_id:this.form.dept_id,//belong_type为2时
  485. start_time:this.monthDateVal2[0], //开始时间 格式示例2022-05-06
  486. end_time:this.monthDateVal2[1], //结束时间 格式示例2022-05-06
  487. }
  488. if(this.alignItem.id&&this.form.kr_id){
  489. params.kr_id=this.form.kr_id; //对齐的KR的ID
  490. }
  491. if(this.alignItem.id&&this.form.o_id){
  492. params.o_id=this.form.o_id; //对齐的KR的ID
  493. }
  494. if(this.addDateParameter2.cycle_type==1){
  495. params.year=this.addDateParameter2.year
  496. params.quarter=0
  497. }
  498. if(this.addDateParameter2.cycle_type==2){
  499. params.year=this.addDateParameter2.year
  500. params.quarter=this.addDateParameter2.dateId
  501. }
  502. if(this.addDateParameter2.cycle_type==3){
  503. params.year=this.addDateParameter2.year
  504. params.half_year=this.addDateParameter2.dateId
  505. }
  506. if(this.addDateParameter2.cycle_type==4){
  507. params.year=this.addDateParameter2.year
  508. params.month=this.addDateParameter2.dateId
  509. }
  510. // console.log(params)
  511. // return false
  512. this.$axiosUser('POST', '/api/pro/okr/obj/create', params).then(res => {
  513. this.$message.success("复制成功");
  514. this.$emit('confirm', {});
  515. this.close();
  516. }).finally(()=>{
  517. this.isShowAdd=false;
  518. });
  519. },
  520. confirmTarget(e){
  521. this.form.o_id='';
  522. this.form.kr_id='';
  523. this.alignItem=e.item;
  524. if(e.type==1){
  525. this.form.o_id=e.item.id
  526. }else if(e.type==2){
  527. this.form.kr_id=e.item.id
  528. }
  529. },
  530. getTargetDateil(){
  531. this.$axiosUser('get', '/api/pro/okr/obj/detail', {object_id:this.id}).then(res => {
  532. let data=res.data.data;
  533. data.owner_userInfo=this.$getEmployeeMapItem(data.owner_id);
  534. data.half_year=data.half_year||1
  535. data.quarter=data.quarter||1
  536. data.month=data.month||1
  537. data.dateStr=getDateStr(data)
  538. if(data.visible_type==5){//部门可见
  539. this.dept_tree = this.$getCache('dept_tree');
  540. data.special_dept_ids.forEach(id=>{
  541. this.getDept(id,this.dept_tree);
  542. })
  543. }
  544. this.dept_selected.dept = this.depts
  545. data.joiner_items=data.joiner_ids.map(id=>{
  546. return this.$getEmployeeMapItem(id);
  547. })
  548. data.special_employee_items=data.special_employee_ids.map(id=>{
  549. return this.$getEmployeeMapItem(id);
  550. })
  551. data.krs.map(item=>{
  552. item.userInfo=this.$getEmployeeMapItem(item.owner_id)
  553. })
  554. this.addDateParameter2={year:data.year,cycle_type:data.cycle_type,dateId:getDateStr(data,true),name:data.dateStr};
  555. this.monthDateVal2=[data.start_time,data.end_time]
  556. this.krs=data.krs;
  557. this.form=data
  558. })
  559. },
  560. //设置默认部门
  561. getDept(id, arr) {
  562. for (let i = 0; i < arr.length; i++) {
  563. if (id == arr[i].id) {
  564. this.depts.push({
  565. dept_id: arr[i].id,
  566. dept_name: arr[i].name
  567. })
  568. break;
  569. } else if (arr[i].children) {
  570. this.getDept(id, arr[i].children);
  571. }
  572. }
  573. },
  574. selectTargetType(item){
  575. this.form.belong_type=item.id; //归属类型 1 公司 2 部门 3 团队 4 个人
  576. this.form.dept_id=item.dept_id
  577. },
  578. //打开Dialog的回调,用刷每次打开都初始化selected
  579. openDialog() {
  580. let month=[];
  581. for (let i = 1; i < 13; i++) {
  582. month.push({ value: i, label: i+'月'})
  583. }
  584. this.monthArr=month;
  585. },
  586. addTab(is){
  587. if(is){
  588. if(!this.form.name){
  589. this.$message.error("目标名称不能为空");
  590. return false
  591. }
  592. if(this.form.visible_type==4&&this.form.special_employee_ids.length==0){
  593. this.$message.error("请选择指定成员");
  594. return false
  595. }
  596. if(this.form.visible_type==5&&this.form.special_dept_ids.length==0){
  597. this.$message.error("请选择指定部门");
  598. return false
  599. }
  600. this.tabIndex++;
  601. this.accomplish++;
  602. }else{
  603. this.tabIndex--;
  604. this.accomplish--;
  605. }
  606. },
  607. close_before(done) {
  608. this.close();
  609. done();
  610. },
  611. //关闭||清空数据
  612. close() {
  613. this.$emit('update:visible', false);
  614. this.alignItem={};
  615. this.employee_selected_all= { dept: [], employee: [] };
  616. this.show_employee_selector_all= false;
  617. this.selectUserIndex=0;//选人组件 区分不同地方调用组件的标识
  618. this.employee_selected= { dept: [], employee: [] };
  619. },
  620. }
  621. };
  622. </script>
  623. <style scoped lang="scss">
  624. .add-task-item{
  625. position: relative;
  626. }
  627. .add-task-item ::v-deep input {
  628. border: none;
  629. padding-right: 80px;
  630. }
  631. .add-task-item:hover i{
  632. cursor: pointer;
  633. opacity: 1 !important;
  634. }
  635. .weight{
  636. width: 90px;
  637. margin-right: 5px;
  638. padding: 5px;
  639. border: 1px dotted #fff;
  640. border-radius: 5px;
  641. cursor: pointer;
  642. }
  643. .weight:hover{
  644. border: 1px dotted #ccc;
  645. }
  646. .weight span{
  647. display: inline-block;
  648. width: 50px;
  649. text-align: center;
  650. color: #e6a23c;
  651. }
  652. .form{
  653. margin: 30px 0;
  654. }
  655. .inputDc {
  656. position: absolute;
  657. top: 0;
  658. right: 0;
  659. left: 0;
  660. bottom: 0;
  661. z-index: 9;
  662. cursor: pointer;
  663. }
  664. /* 方法二 */
  665. .tabActive{
  666. background-color: #409EFF !important;
  667. color: #fff !important;
  668. }
  669. .accomplish{
  670. background-color: #67c23a !important;
  671. color: #fff !important;
  672. }
  673. .stepNew {
  674. margin: 0px auto;
  675. }
  676. .stepNew div {
  677. width: 240px;
  678. height: 36px;
  679. line-height: 36px;
  680. text-align: center;
  681. vertical-align: text-bottom;
  682. font-size: 15px;
  683. }
  684. .border {
  685. -webkit-appearance: none;
  686. background-color: #fff;
  687. background-image: none;
  688. border-radius: 4px;
  689. border: 1px solid #dcdfe6;
  690. -webkit-box-sizing: border-box;
  691. box-sizing: border-box;
  692. color: #C0C4CF;
  693. font-size: inherit;
  694. height: auto;
  695. outline: 0;
  696. padding: 0 15px;
  697. padding-right: 10px;
  698. line-height: 34px;
  699. width: 300px;
  700. position: relative;
  701. cursor: pointer;
  702. }
  703. .border .font-flex-word{
  704. color: #606266;
  705. }
  706. .border:hover{
  707. border: 1px solid #c0c4cc;
  708. }
  709. /* */
  710. .stepOneN {
  711. position: relative;
  712. background: #edeff5;
  713. border-top-left-radius: 18px;
  714. border-bottom-left-radius: 18px;
  715. }
  716. .stepOneN span:nth-of-type(1) {
  717. border-width: 18px 0 18px 18px;
  718. border-style: solid;
  719. border-color: #fff transparent #fff transparent;
  720. position: absolute;
  721. top: 0;
  722. right: 0;
  723. }
  724. /* */
  725. .stepTwoN {
  726. position: relative;
  727. background: #edeff5;
  728. }
  729. .stepTwoN span:nth-of-type(1) {
  730. border-width: 18px 0 18px 18px;
  731. border-style: solid;
  732. border-color: transparent transparent transparent #fff;
  733. position: absolute;
  734. top: 0;
  735. left: 0;
  736. }
  737. .stepTwoN span:nth-of-type(2) {
  738. border-width: 18px 0 18px 18px;
  739. border-style: solid;
  740. border-color: #fff transparent #fff transparent;
  741. position: absolute;
  742. top: 0;
  743. right: 0;
  744. }
  745. /* */
  746. .stepThreeN {
  747. position: relative;
  748. background: #edeff5;
  749. border-top-right-radius: 18px;
  750. border-bottom-right-radius: 18px;
  751. }
  752. .stepThreeN span:nth-of-type(1) {
  753. border-width: 18px 0 18px 18px;
  754. border-style: solid;
  755. border-color: transparent transparent transparent #fff;
  756. position: absolute;
  757. top: 0;
  758. left: 0;
  759. }
  760. .noBj ::v-deep .el-input__inner,.noBj ::v-deep .el-textarea__inner {
  761. background-color: #F5F8FA;
  762. }
  763. ::v-deep .el-input-group__append {
  764. padding: 0 10px;
  765. }
  766. ::v-deep .el-collapse-item__header {
  767. padding: 10px;
  768. height: auto;
  769. line-height: normal;
  770. }
  771. ::v-deep .el-collapse-item__content {
  772. padding: 0;
  773. }
  774. ::v-deep .el-dialog__body {
  775. padding: 20px;
  776. }
  777. ::v-deep .el-form-item {
  778. margin-bottom: 16px;
  779. }
  780. .noBorder ::v-deep .el-input__inner, ::v-deep .el-textarea__inner {
  781. border: none;
  782. border-bottom: 1px solid #DCDFE6;
  783. border-radius: 0px;
  784. }
  785. </style>